[COMMENTS]
[reactos.git] / rostests / kmtests / rtl / RtlRegistry.c
1 /*
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>
6 */
7
8 #define KMT_EMULATE_KERNEL
9 #include <kmt_test.h>
10
11 #ifdef KMT_KERNEL_MODE
12 #define KMT_KERNEL_HANDLE OBJ_KERNEL_HANDLE
13 #else
14 #define KMT_KERNEL_HANDLE 0
15 #endif
16
17 #ifndef RTL_NUMBER_OF
18 #define RTL_NUMBER_OF(x) (sizeof(x) / sizeof(x[0]))
19 #endif
20
21 typedef struct
22 {
23 PCWSTR ValueName;
24 ULONG ValueType;
25 PVOID ValueData;
26 ULONG ValueLength;
27 } EXPECTED_VALUE, *PEXPECTED_VALUE;
28
29 typedef struct
30 {
31 ULONG Count;
32 ULONG CurrentIndex;
33 EXPECTED_VALUE Values[20];
34 } EXPECTED_VALUES, *PEXPECTED_VALUES;
35
36 //static RTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
37 static
38 NTSTATUS
39 NTAPI
40 QueryRoutine(
41 _In_ PWSTR ValueName,
42 _In_ ULONG ValueType,
43 _In_ PVOID ValueData,
44 _In_ ULONG ValueLength,
45 _In_ PVOID Context,
46 _In_ PVOID EntryContext)
47 {
48 PEXPECTED_VALUES ExpectedValues = Context;
49 PEXPECTED_VALUE Expected;
50 SIZE_T EqualBytes;
51
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"))
56 {
57 Expected = &ExpectedValues->Values[ExpectedValues->CurrentIndex];
58 if (EntryContext)
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,
64 Expected->ValueData,
65 min(ValueLength, Expected->ValueLength));
66 ok_eq_size(EqualBytes, Expected->ValueLength);
67 }
68
69 ExpectedValues->CurrentIndex++;
70 return STATUS_SUCCESS;
71 }
72
73 static
74 VOID
75 TestRtlQueryRegistryValues(
76 _In_ HANDLE KeyHandle)
77 {
78 NTSTATUS Status;
79 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"TestValue");
80 RTL_QUERY_REGISTRY_TABLE QueryTable[] =
81 {
82 { QueryRoutine, 0, L"TestValue", NULL, REG_NONE, NULL, 0 },
83 { NULL }
84 };
85 EXPECTED_VALUES Expected;
86 typedef struct
87 {
88 PWSTR Str;
89 ULONG Len;
90 } STR_AND_LEN;
91 #define CONST_STR_AND_LEN(d) { (d), sizeof(d) }
92 #define CSAL CONST_STR_AND_LEN
93
94 #define NO_AUTO_LEN 1
95 #define NO_DEFAULT 2
96 #define AUTO_DIFFERS 4
97 #define DEFAULT_DIFFERS 8
98 struct
99 {
100 STR_AND_LEN Value;
101 ULONG ExpectedCount;
102 STR_AND_LEN Expected[20];
103 ULONG Flags;
104 ULONG DefaultExpectedCount;
105 STR_AND_LEN DefaultExpected[20];
106
107 } Tests[] =
108 {
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") } },
120 };
121
122 #define DO_QUERY(ExpectedArray, ExpectedCount) do \
123 { \
124 ULONG _i; \
125 for (_i = 0; _i < (ExpectedCount); _i++) \
126 { \
127 Expected.Values[_i].ValueName = ValueName.Buffer; \
128 Expected.Values[_i].ValueType = REG_SZ; \
129 Expected.Values[_i].ValueData = (ExpectedArray)[_i].Str; \
130 Expected.Values[_i].ValueLength = (ExpectedArray)[_i].Len; \
131 } \
132 Expected.CurrentIndex = 0; \
133 Expected.Count = (ExpectedCount); \
134 if ((ExpectedCount) == 1) \
135 QueryTable[0].EntryContext = &Expected.Values[0]; \
136 else \
137 QueryTable[0].EntryContext = NULL; \
138 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, \
139 (PCWSTR)KeyHandle, \
140 QueryTable, \
141 &Expected, \
142 NULL); \
143 ok_eq_hex(Status, STATUS_SUCCESS); \
144 ok_eq_ulong(Expected.CurrentIndex, Expected.Count); \
145 } while(0)
146
147 ULONG TestCount = RTL_NUMBER_OF(Tests);
148 ULONG i;
149
150 for (i = 0; i < TestCount; i++)
151 {
152 trace("Set: %lu\n", i);
153 Status = ZwSetValueKey(KeyHandle,
154 &ValueName,
155 0,
156 REG_MULTI_SZ,
157 Tests[i].Value.Str,
158 Tests[i].Value.Len);
159 ok_eq_hex(Status, STATUS_SUCCESS);
160
161 DO_QUERY(Tests[i].Expected, Tests[i].ExpectedCount);
162 }
163
164 /* Delete value to test default values */
165 Status = ZwDeleteValueKey(KeyHandle, &ValueName);
166 ok(Status == STATUS_SUCCESS || Status == STATUS_OBJECT_NAME_NOT_FOUND,
167 "ZwDeleteValueKey returned %lx\n", Status);
168
169 /* Default: REG_NONE */
170 DO_QUERY((STR_AND_LEN *)NULL, 0);
171
172 for (i = 0; i < TestCount; i++)
173 {
174 if (Tests[i].Flags & NO_DEFAULT)
175 continue;
176 trace("Default: %lu\n", i);
177 QueryTable[0].DefaultType = REG_MULTI_SZ;
178 QueryTable[0].DefaultData = Tests[i].Value.Str;
179 QueryTable[0].DefaultLength = Tests[i].Value.Len;
180
181 if (Tests[i].Flags & DEFAULT_DIFFERS)
182 DO_QUERY(Tests[i].DefaultExpected, Tests[i].DefaultExpectedCount);
183 else
184 DO_QUERY(Tests[i].Expected, Tests[i].ExpectedCount);
185 }
186
187 for (i = 0; i < TestCount; i++)
188 {
189 if (Tests[i].Flags & NO_AUTO_LEN)
190 continue;
191 trace("Auto: %lu\n", i);
192 QueryTable[0].DefaultType = REG_MULTI_SZ;
193 QueryTable[0].DefaultData = Tests[i].Value.Str;
194 QueryTable[0].DefaultLength = 0;
195
196 if (Tests[i].Flags & AUTO_DIFFERS)
197 DO_QUERY(Tests[i].DefaultExpected, Tests[i].DefaultExpectedCount);
198 else
199 DO_QUERY(Tests[i].Expected, Tests[i].ExpectedCount);
200 }
201 }
202
203 START_TEST(RtlRegistry)
204 {
205 NTSTATUS Status;
206 UNICODE_STRING KeyName;
207 OBJECT_ATTRIBUTES ObjectAttributes;
208 HANDLE SoftwareHandle;
209 HANDLE KeyHandle;
210
211 RtlInitUnicodeString(&KeyName, L"\\Registry\\MACHINE\\Software");
212 InitializeObjectAttributes(&ObjectAttributes,
213 &KeyName,
214 OBJ_CASE_INSENSITIVE | KMT_KERNEL_HANDLE,
215 NULL,
216 NULL);
217 Status = ZwOpenKey(&SoftwareHandle,
218 KEY_CREATE_SUB_KEY,
219 &ObjectAttributes);
220 ok_eq_hex(Status, STATUS_SUCCESS);
221 if (skip(NT_SUCCESS(Status) && SoftwareHandle != NULL, "No software key\n"))
222 return;
223
224 RtlInitUnicodeString(&KeyName, L"RtlRegistryKmtestKey");
225 InitializeObjectAttributes(&ObjectAttributes,
226 &KeyName,
227 OBJ_CASE_INSENSITIVE | KMT_KERNEL_HANDLE,
228 SoftwareHandle,
229 NULL);
230 Status = ZwCreateKey(&KeyHandle,
231 KEY_QUERY_VALUE | KEY_SET_VALUE | DELETE,
232 &ObjectAttributes,
233 0,
234 NULL,
235 REG_OPTION_VOLATILE,
236 NULL);
237 ok_eq_hex(Status, STATUS_SUCCESS);
238
239 if (!skip(NT_SUCCESS(Status) && KeyHandle != NULL, "No test key\n"))
240 {
241 TestRtlQueryRegistryValues(KeyHandle);
242
243 Status = ZwDeleteKey(KeyHandle);
244 ok_eq_hex(Status, STATUS_SUCCESS);
245 Status = ZwClose(KeyHandle);
246 ok_eq_hex(Status, STATUS_SUCCESS);
247 }
248 }