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>
13 Test_KeyFullInformation(void)
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
;
23 OBJECT_ATTRIBUTES ObjectAttributes
;
26 FullInformationLength
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[100]);
27 FullInformation
= RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInformationLength
);
30 skip("Out of memory\n");
34 InitializeObjectAttributes(&ObjectAttributes
,
39 Status
= NtOpenKey(&HKLM_Key
, KEY_READ
, &ObjectAttributes
);
40 ok_ntstatus(Status
, STATUS_SUCCESS
);
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
);
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]);
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
);
71 InitializeObjectAttributes(&ObjectAttributes
,
76 Status
= NtOpenKey(&HKLM_Software_Key
, KEY_READ
, &ObjectAttributes
);
77 ok_ntstatus(Status
, STATUS_SUCCESS
);
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]);
96 InitializeObjectAttributes(&ObjectAttributes
,
101 Status
= NtCreateKey(&Test_Key
, KEY_ALL_ACCESS
, &ObjectAttributes
, 0, &MyClass
, REG_OPTION_VOLATILE
, NULL
);
102 ok_ntstatus(Status
, STATUS_SUCCESS
);
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
);
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]);
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]);
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]);
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]);
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]);
176 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInformation
);
178 Status
= NtDeleteKey(Test_Key
);
179 ok_ntstatus(Status
, STATUS_SUCCESS
);
182 NtClose(HKLM_Software_Key
);
188 Test_KeyNameInformation(void)
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
;
197 OBJECT_ATTRIBUTES ObjectAttributes
;
200 /* Open the HKCU key */
201 InitializeObjectAttributes(&ObjectAttributes
,
203 OBJ_CASE_INSENSITIVE
,
206 Status
= NtOpenKey(&HKLM_Key
, KEY_READ
, &ObjectAttributes
);
207 ok_ntstatus(Status
, STATUS_SUCCESS
);
209 /* Get the name info length */
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
)]));
215 /* Get it for real */
216 NameInformation
= RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength
);
217 if (!NameInformation
)
219 skip("Out of memory\n");
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
);
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
);
234 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation
);
236 /* Open one subkey */
237 InitializeObjectAttributes(&ObjectAttributes
,
239 OBJ_CASE_INSENSITIVE
,
242 Status
= NtOpenKey(&HKLM_Software_Key
, KEY_READ
, &ObjectAttributes
);
243 ok_ntstatus(Status
, STATUS_SUCCESS
);
245 /* Get the name info length */
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
)]));
251 /* Get it for real */
252 NameInformation
= RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength
);
253 ok(NameInformation
!= NULL
, "\n");
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
);
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
);
266 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation
);
268 NtClose(HKLM_Software_Key
);
272 START_TEST(NtQueryKey
)
274 Test_KeyFullInformation();
275 Test_KeyNameInformation();