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