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
12 #define RTL_NUMBER_OF(x) (sizeof(x) / sizeof(x[0]))
21 } EXPECTED_VALUE
, *PEXPECTED_VALUE
;
27 EXPECTED_VALUE Values
[20];
28 } EXPECTED_VALUES
, *PEXPECTED_VALUES
;
30 //static RTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
38 _In_ ULONG ValueLength
,
40 _In_ PVOID EntryContext
)
42 PEXPECTED_VALUES ExpectedValues
= Context
;
43 PEXPECTED_VALUE Expected
;
46 ok(ExpectedValues
->CurrentIndex
< ExpectedValues
->Count
,
47 "Call number %lu, expected only %lu\n",
48 ExpectedValues
->CurrentIndex
, ExpectedValues
->Count
);
49 if (!skip(ExpectedValues
->CurrentIndex
< ExpectedValues
->Count
, "Out of bounds\n"))
51 Expected
= &ExpectedValues
->Values
[ExpectedValues
->CurrentIndex
];
53 ok_eq_pointer(EntryContext
, Expected
);
54 ok_eq_wstr(ValueName
, Expected
->ValueName
);
55 ok_eq_ulong(ValueType
, Expected
->ValueType
);
56 ok_eq_ulong(ValueLength
, Expected
->ValueLength
);
57 EqualBytes
= RtlCompareMemory(ValueData
,
59 min(ValueLength
, Expected
->ValueLength
));
60 ok_eq_size(EqualBytes
, Expected
->ValueLength
);
63 ExpectedValues
->CurrentIndex
++;
64 return STATUS_SUCCESS
;
69 TestRtlQueryRegistryValues(
70 _In_ HANDLE KeyHandle
)
73 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"TestValue");
74 RTL_QUERY_REGISTRY_TABLE QueryTable
[] =
76 { QueryRoutine
, 0, L
"TestValue", NULL
, REG_NONE
, NULL
, 0 },
79 EXPECTED_VALUES Expected
;
85 #define CONST_STR_AND_LEN(d) { (d), sizeof(d) }
86 #define CSAL CONST_STR_AND_LEN
90 #define AUTO_DIFFERS 4
91 #define DEFAULT_DIFFERS 8
96 STR_AND_LEN Expected
[20];
98 ULONG DefaultExpectedCount
;
99 STR_AND_LEN DefaultExpected
[20];
103 { { NULL
, 0 }, 0, { { NULL
, 0 } }, NO_AUTO_LEN
| NO_DEFAULT
},
104 { CSAL(L
""), 0, { { NULL
, 0 } }, NO_AUTO_LEN
},
105 { CSAL(L
"\0"), 1, { CSAL(L
"") },
106 AUTO_DIFFERS
| DEFAULT_DIFFERS
, 0, { { NULL
, 0 } } },
107 { CSAL(L
"String"), 1, { CSAL(L
"String") }, NO_AUTO_LEN
},
108 { CSAL(L
"String\0"), 1, { CSAL(L
"String") } },
109 { CSAL(L
"String1\0String2"), 2, { CSAL(L
"String1"), CSAL(L
"String2") }, NO_AUTO_LEN
},
110 { CSAL(L
"String1\0String2\0"), 2, { CSAL(L
"String1"), CSAL(L
"String2") } },
111 { CSAL(L
"String1\0\0String3"), 3, { CSAL(L
"String1"), CSAL(L
""), CSAL(L
"String3") }, NO_AUTO_LEN
},
112 { CSAL(L
"String1\0\0String3\0"), 3, { CSAL(L
"String1"), CSAL(L
""), CSAL(L
"String3") },
113 AUTO_DIFFERS
, 1, { CSAL(L
"String1") } },
116 #define DO_QUERY(ExpectedArray, ExpectedCount) do \
119 ULONG _ExpectedCount = (ExpectedCount); \
120 for (_i = 0; _i < _ExpectedCount; _i++) \
122 Expected.Values[_i].ValueName = ValueName.Buffer; \
123 Expected.Values[_i].ValueType = REG_SZ; \
124 Expected.Values[_i].ValueData = (ExpectedArray)[_i].Str; \
125 Expected.Values[_i].ValueLength = (ExpectedArray)[_i].Len; \
127 Expected.CurrentIndex = 0; \
128 Expected.Count = _ExpectedCount; \
129 if (_ExpectedCount == 1) \
130 QueryTable[0].EntryContext = &Expected.Values[0]; \
132 QueryTable[0].EntryContext = NULL; \
133 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, \
138 ok_eq_hex(Status, STATUS_SUCCESS); \
139 ok_eq_ulong(Expected.CurrentIndex, Expected.Count); \
142 ULONG TestCount
= RTL_NUMBER_OF(Tests
);
145 for (i
= 0; i
< TestCount
; i
++)
147 trace("Set: %lu\n", i
);
148 Status
= ZwSetValueKey(KeyHandle
,
154 ok_eq_hex(Status
, STATUS_SUCCESS
);
156 DO_QUERY(Tests
[i
].Expected
, Tests
[i
].ExpectedCount
);
159 /* Delete value to test default values */
160 Status
= ZwDeleteValueKey(KeyHandle
, &ValueName
);
161 ok(Status
== STATUS_SUCCESS
|| Status
== STATUS_OBJECT_NAME_NOT_FOUND
,
162 "ZwDeleteValueKey returned %lx\n", Status
);
164 /* Default: REG_NONE */
165 DO_QUERY((STR_AND_LEN
*)NULL
, 0);
167 for (i
= 0; i
< TestCount
; i
++)
169 if (Tests
[i
].Flags
& NO_DEFAULT
)
171 trace("Default: %lu\n", i
);
172 QueryTable
[0].DefaultType
= REG_MULTI_SZ
;
173 QueryTable
[0].DefaultData
= Tests
[i
].Value
.Str
;
174 QueryTable
[0].DefaultLength
= Tests
[i
].Value
.Len
;
176 if (Tests
[i
].Flags
& DEFAULT_DIFFERS
)
177 DO_QUERY(Tests
[i
].DefaultExpected
, Tests
[i
].DefaultExpectedCount
);
179 DO_QUERY(Tests
[i
].Expected
, Tests
[i
].ExpectedCount
);
182 for (i
= 0; i
< TestCount
; i
++)
184 if (Tests
[i
].Flags
& NO_AUTO_LEN
)
186 trace("Auto: %lu\n", i
);
187 QueryTable
[0].DefaultType
= REG_MULTI_SZ
;
188 QueryTable
[0].DefaultData
= Tests
[i
].Value
.Str
;
189 QueryTable
[0].DefaultLength
= 0;
191 if (Tests
[i
].Flags
& AUTO_DIFFERS
)
192 DO_QUERY(Tests
[i
].DefaultExpected
, Tests
[i
].DefaultExpectedCount
);
194 DO_QUERY(Tests
[i
].Expected
, Tests
[i
].ExpectedCount
);
198 START_TEST(RtlRegistry
)
201 UNICODE_STRING KeyName
;
202 OBJECT_ATTRIBUTES ObjectAttributes
;
203 HANDLE SoftwareHandle
;
206 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\MACHINE\\Software");
207 InitializeObjectAttributes(&ObjectAttributes
,
209 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
212 Status
= ZwOpenKey(&SoftwareHandle
,
215 ok_eq_hex(Status
, STATUS_SUCCESS
);
216 if (skip(NT_SUCCESS(Status
) && SoftwareHandle
!= NULL
, "No software key\n"))
219 RtlInitUnicodeString(&KeyName
, L
"RtlRegistryKmtestKey");
220 InitializeObjectAttributes(&ObjectAttributes
,
222 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
225 Status
= ZwCreateKey(&KeyHandle
,
226 KEY_QUERY_VALUE
| KEY_SET_VALUE
| DELETE
,
232 ok_eq_hex(Status
, STATUS_SUCCESS
);
234 if (!skip(NT_SUCCESS(Status
) && KeyHandle
!= NULL
, "No test key\n"))
236 TestRtlQueryRegistryValues(KeyHandle
);
238 Status
= ZwDeleteKey(KeyHandle
);
239 ok_eq_hex(Status
, STATUS_SUCCESS
);
240 Status
= ZwClose(KeyHandle
);
241 ok_eq_hex(Status
, STATUS_SUCCESS
);