[TASKMGR] Process page: Allow using "Open File Location" functionality without runnin...
[reactos.git] / modules / rostests / apitests / ntdll / NtQueryKey.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Tests for the NtQueryKey API
5 * PROGRAMMER: Jérôme Gardou <jerome.gardou@reactos.org>
6 * Thomas Faber <thomas.faber@reactos.org>
7 */
8
9 #include "precomp.h"
10
11 static
12 void
13 Test_KeyFullInformation(void)
14 {
15 UNICODE_STRING HKLM_Name = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
16 UNICODE_STRING Software_Name = RTL_CONSTANT_STRING(L"Software");
17 UNICODE_STRING Test_Name = RTL_CONSTANT_STRING(L"NtQueryKey_apitest");
18 UNICODE_STRING MyClass = RTL_CONSTANT_STRING(L"MyClass");
19 HANDLE HKLM_Key, HKLM_Software_Key, Test_Key;
20 ULONG FullInformationLength;
21 PKEY_FULL_INFORMATION FullInformation;
22 ULONG InfoLength;
23 OBJECT_ATTRIBUTES ObjectAttributes;
24 NTSTATUS Status;
25
26 FullInformationLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class[100]);
27 FullInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInformationLength);
28 if (!FullInformation)
29 {
30 skip("Out of memory\n");
31 return;
32 }
33
34 InitializeObjectAttributes(&ObjectAttributes,
35 &HKLM_Name,
36 OBJ_CASE_INSENSITIVE,
37 NULL,
38 NULL);
39 Status = NtOpenKey(&HKLM_Key, KEY_READ, &ObjectAttributes);
40 ok_ntstatus(Status, STATUS_SUCCESS);
41
42 InfoLength = 0x55555555;
43 Status = NtQueryKey(HKLM_Key, KeyFullInformation, NULL, 0, &InfoLength);
44 ok(Status == STATUS_BUFFER_TOO_SMALL, "Status = 0x%lx\n", Status);
45 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength);
46
47 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
48 InfoLength = 0x55555555;
49 Status = NtQueryKey(HKLM_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class), &InfoLength);
50 ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
51 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength);
52 ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n");
53 ok(FullInformation->TitleIndex == 0, "TitleIndex = %lu\n", FullInformation->TitleIndex);
54 ok(FullInformation->ClassOffset == 0xffffffff, "ClassOffset = %lu\n", FullInformation->ClassOffset);
55 ok(FullInformation->ClassLength == 0, "ClassLength = %lu\n", FullInformation->ClassLength);
56 ok(FullInformation->SubKeys >= 5 && FullInformation->SubKeys < 20, "SubKeys = %lu\n", FullInformation->SubKeys);
57 ok(FullInformation->MaxNameLen >= 8 * sizeof(WCHAR) && FullInformation->MaxNameLen < 100 * sizeof(WCHAR), "MaxNameLen = %lu\n", FullInformation->MaxNameLen);
58 ok(FullInformation->MaxClassLen != 0x55555555 && FullInformation->MaxClassLen % sizeof(WCHAR) == 0, "MaxClassLen = %lu\n", FullInformation->MaxClassLen);
59 ok(FullInformation->Values != 0x55555555, "Values = %lu\n", FullInformation->Values);
60 ok(FullInformation->MaxValueNameLen != 0x55555555 && FullInformation->MaxValueNameLen % sizeof(WCHAR) == 0, "MaxValueNameLen = %lu\n", FullInformation->MaxValueNameLen);
61 ok(FullInformation->MaxValueDataLen != 0x55555555, "MaxValueDataLen = %lu\n", FullInformation->MaxValueDataLen);
62 ok(FullInformation->Class[0] == 0x5555, "Class[0] = %u\n", FullInformation->Class[0]);
63
64 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
65 InfoLength = 0x55555555;
66 Status = NtQueryKey(HKLM_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) - 1, &InfoLength);
67 ok(Status == STATUS_BUFFER_TOO_SMALL, "Status = 0x%lx\n", Status);
68 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength);
69 ok(FullInformation->LastWriteTime.QuadPart == 0x5555555555555555, "LastWriteTime changed: %I64d\n", FullInformation->LastWriteTime.QuadPart);
70
71 InitializeObjectAttributes(&ObjectAttributes,
72 &Software_Name,
73 OBJ_CASE_INSENSITIVE,
74 HKLM_Key,
75 NULL);
76 Status = NtOpenKey(&HKLM_Software_Key, KEY_READ, &ObjectAttributes);
77 ok_ntstatus(Status, STATUS_SUCCESS);
78
79 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
80 InfoLength = 0x55555555;
81 Status = NtQueryKey(HKLM_Software_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class), &InfoLength);
82 ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
83 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength);
84 ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n");
85 ok(FullInformation->TitleIndex == 0, "TitleIndex = %lu\n", FullInformation->TitleIndex);
86 ok(FullInformation->ClassOffset == 0xffffffff, "ClassOffset = %lu\n", FullInformation->ClassOffset);
87 ok(FullInformation->ClassLength == 0, "ClassLength = %lu\n", FullInformation->ClassLength);
88 ok(FullInformation->SubKeys >= 5 && FullInformation->SubKeys < 1000, "SubKeys = %lu\n", FullInformation->SubKeys);
89 ok(FullInformation->MaxNameLen >= 8 * sizeof(WCHAR), "MaxNameLen = %lu\n", FullInformation->MaxNameLen);
90 ok(FullInformation->MaxClassLen != 0x55555555 && FullInformation->MaxClassLen % sizeof(WCHAR) == 0, "MaxClassLen = %lu\n", FullInformation->MaxClassLen);
91 ok(FullInformation->Values != 0x55555555, "Values = %lu\n", FullInformation->Values);
92 ok(FullInformation->MaxValueNameLen != 0x55555555 && FullInformation->MaxValueNameLen % sizeof(WCHAR) == 0, "MaxValueNameLen = %lu\n", FullInformation->MaxValueNameLen);
93 ok(FullInformation->MaxValueDataLen != 0x55555555, "MaxValueDataLen = %lu\n", FullInformation->MaxValueDataLen);
94 ok(FullInformation->Class[0] == 0x5555, "Class[0] = %u\n", FullInformation->Class[0]);
95
96 InitializeObjectAttributes(&ObjectAttributes,
97 &Test_Name,
98 OBJ_CASE_INSENSITIVE,
99 HKLM_Software_Key,
100 NULL);
101 Status = NtCreateKey(&Test_Key, KEY_ALL_ACCESS, &ObjectAttributes, 0, &MyClass, REG_OPTION_VOLATILE, NULL);
102 ok_ntstatus(Status, STATUS_SUCCESS);
103
104 InfoLength = 0x55555555;
105 Status = NtQueryKey(Test_Key, KeyFullInformation, NULL, 0, &InfoLength);
106 ok(Status == STATUS_BUFFER_TOO_SMALL, "Status = 0x%lx\n", Status);
107 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength);
108
109 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
110 InfoLength = 0x55555555;
111 Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class), &InfoLength);
112 ok(Status == STATUS_BUFFER_OVERFLOW, "Status = 0x%lx\n", Status);
113 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength);
114 ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n");
115 ok(FullInformation->TitleIndex == 0, "TitleIndex = %lu\n", FullInformation->TitleIndex);
116 ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset);
117 ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength);
118 ok(FullInformation->SubKeys == 0, "SubKeys = %lu\n", FullInformation->SubKeys);
119 ok(FullInformation->MaxNameLen == 0, "MaxNameLen = %lu\n", FullInformation->MaxNameLen);
120 ok(FullInformation->MaxClassLen == 0, "MaxClassLen = %lu\n", FullInformation->MaxClassLen);
121 ok(FullInformation->Values == 0, "Values = %lu\n", FullInformation->Values);
122 ok(FullInformation->MaxValueNameLen == 0, "MaxValueNameLen = %lu\n", FullInformation->MaxValueNameLen);
123 ok(FullInformation->MaxValueDataLen == 0, "MaxValueDataLen = %lu\n", FullInformation->MaxValueDataLen);
124 ok(FullInformation->Class[0] == 0x5555, "Class[0] = %u\n", FullInformation->Class[0]);
125
126 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
127 InfoLength = 0x55555555;
128 Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class[1]), &InfoLength);
129 ok(Status == STATUS_BUFFER_OVERFLOW, "Status = 0x%lx\n", Status);
130 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength);
131 ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n");
132 ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset);
133 ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength);
134 ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]);
135 ok(FullInformation->Class[1] == 0x5555, "Class[1] = %u\n", FullInformation->Class[1]);
136
137 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
138 InfoLength = 0x55555555;
139 Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length - 1, &InfoLength);
140 ok(Status == STATUS_BUFFER_OVERFLOW, "Status = 0x%lx\n", Status);
141 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength);
142 ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n");
143 ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset);
144 ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength);
145 ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]);
146 ok(FullInformation->Class[1] == L'y', "Class[1] = %u\n", FullInformation->Class[1]);
147 ok(FullInformation->Class[6] == (L's' | 0x5500), "Class[6] = %u\n", FullInformation->Class[6]);
148 ok(FullInformation->Class[7] == 0x5555, "Class[7] = %u\n", FullInformation->Class[7]);
149
150 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
151 InfoLength = 0x55555555;
152 Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, &InfoLength);
153 ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
154 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength);
155 ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n");
156 ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset);
157 ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength);
158 ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]);
159 ok(FullInformation->Class[1] == L'y', "Class[1] = %u\n", FullInformation->Class[1]);
160 ok(FullInformation->Class[6] == L's', "Class[6] = %u\n", FullInformation->Class[6]);
161 ok(FullInformation->Class[7] == 0x5555, "Class[7] = %u\n", FullInformation->Class[7]);
162
163 RtlFillMemory(FullInformation, FullInformationLength, 0x55);
164 InfoLength = 0x55555555;
165 Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length + sizeof(UNICODE_NULL), &InfoLength);
166 ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
167 ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength);
168 ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n");
169 ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset);
170 ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength);
171 ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]);
172 ok(FullInformation->Class[1] == L'y', "Class[1] = %u\n", FullInformation->Class[1]);
173 ok(FullInformation->Class[6] == L's', "Class[6] = %u\n", FullInformation->Class[6]);
174 ok(FullInformation->Class[7] == 0x5555, "Class[7] = %u\n", FullInformation->Class[7]);
175
176 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInformation);
177
178 Status = NtDeleteKey(Test_Key);
179 ok_ntstatus(Status, STATUS_SUCCESS);
180
181 NtClose(Test_Key);
182 NtClose(HKLM_Software_Key);
183 NtClose(HKLM_Key);
184 }
185
186 static
187 void
188 Test_KeyNameInformation(void)
189 {
190 UNICODE_STRING HKLM_Name = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
191 UNICODE_STRING HKLM_Software_Name = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software");
192 UNICODE_STRING Software_Name = RTL_CONSTANT_STRING(L"Software");
193 UNICODE_STRING InfoName;
194 HANDLE HKLM_Key, HKLM_Software_Key;
195 PKEY_NAME_INFORMATION NameInformation;
196 ULONG InfoLength;
197 OBJECT_ATTRIBUTES ObjectAttributes;
198 NTSTATUS Status;
199
200 /* Open the HKCU key */
201 InitializeObjectAttributes(&ObjectAttributes,
202 &HKLM_Name,
203 OBJ_CASE_INSENSITIVE,
204 NULL,
205 NULL);
206 Status = NtOpenKey(&HKLM_Key, KEY_READ, &ObjectAttributes);
207 ok_ntstatus(Status, STATUS_SUCCESS);
208
209 /* Get the name info length */
210 InfoLength = 0;
211 Status = NtQueryKey(HKLM_Key, KeyNameInformation, NULL, 0, &InfoLength);
212 ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
213 ok_size_t(InfoLength, FIELD_OFFSET(KEY_NAME_INFORMATION, Name[HKLM_Name.Length/sizeof(WCHAR)]));
214
215 /* Get it for real */
216 NameInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength);
217 if (!NameInformation)
218 {
219 skip("Out of memory\n");
220 return;
221 }
222
223 Status = NtQueryKey(HKLM_Key, KeyNameInformation, NameInformation, InfoLength, &InfoLength);
224 ok_ntstatus(Status, STATUS_SUCCESS);
225 ok_size_t(InfoLength, FIELD_OFFSET(KEY_NAME_INFORMATION, Name[HKLM_Name.Length/sizeof(WCHAR)]));
226 ok_size_t(NameInformation->NameLength, HKLM_Name.Length);
227
228 InfoName.Buffer = NameInformation->Name;
229 InfoName.Length = NameInformation->NameLength;
230 InfoName.MaximumLength = NameInformation->NameLength;
231 ok(RtlCompareUnicodeString(&InfoName, &HKLM_Name, TRUE) == 0, "%.*S\n",
232 InfoName.Length, InfoName.Buffer);
233
234 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
235
236 /* Open one subkey */
237 InitializeObjectAttributes(&ObjectAttributes,
238 &Software_Name,
239 OBJ_CASE_INSENSITIVE,
240 HKLM_Key,
241 NULL);
242 Status = NtOpenKey(&HKLM_Software_Key, KEY_READ, &ObjectAttributes);
243 ok_ntstatus(Status, STATUS_SUCCESS);
244
245 /* Get the name info length */
246 InfoLength = 0;
247 Status = NtQueryKey(HKLM_Software_Key, KeyNameInformation, NULL, 0, &InfoLength);
248 ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
249 ok_size_t(InfoLength, FIELD_OFFSET(KEY_NAME_INFORMATION, Name[HKLM_Software_Name.Length/sizeof(WCHAR)]));
250
251 /* Get it for real */
252 NameInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength);
253 ok(NameInformation != NULL, "\n");
254
255 Status = NtQueryKey(HKLM_Software_Key, KeyNameInformation, NameInformation, InfoLength, &InfoLength);
256 ok_ntstatus(Status, STATUS_SUCCESS);
257 ok_size_t(InfoLength, FIELD_OFFSET(KEY_NAME_INFORMATION, Name[HKLM_Software_Name.Length/sizeof(WCHAR)]));
258 ok_size_t(NameInformation->NameLength, HKLM_Software_Name.Length);
259
260 InfoName.Buffer = NameInformation->Name;
261 InfoName.Length = NameInformation->NameLength;
262 InfoName.MaximumLength = NameInformation->NameLength;
263 ok(RtlCompareUnicodeString(&InfoName, &HKLM_Software_Name, TRUE) == 0, "%.*S\n",
264 InfoName.Length, InfoName.Buffer);
265
266 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
267
268 NtClose(HKLM_Software_Key);
269 NtClose(HKLM_Key);
270 }
271
272 START_TEST(NtQueryKey)
273 {
274 Test_KeyFullInformation();
275 Test_KeyNameInformation();
276 }