ReactOS  0.4.13-dev-247-g0f29b3f
NtQueryKey.c
Go to the documentation of this file.
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
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;
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 
35  &HKLM_Name,
37  NULL,
38  NULL);
39  Status = NtOpenKey(&HKLM_Key, KEY_READ, &ObjectAttributes);
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 
72  &Software_Name,
74  HKLM_Key,
75  NULL);
76  Status = NtOpenKey(&HKLM_Software_Key, KEY_READ, &ObjectAttributes);
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 
97  &Test_Name,
99  HKLM_Software_Key,
100  NULL);
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);
180 
181  NtClose(Test_Key);
182  NtClose(HKLM_Software_Key);
183  NtClose(HKLM_Key);
184 }
185 
186 static
187 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;
199 
200  /* Open the HKCU key */
202  &HKLM_Name,
204  NULL,
205  NULL);
206  Status = NtOpenKey(&HKLM_Key, KEY_READ, &ObjectAttributes);
208 
209  /* Get the name info length */
210  InfoLength = 0;
211  Status = NtQueryKey(HKLM_Key, KeyNameInformation, NULL, 0, &InfoLength);
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);
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 */
238  &Software_Name,
240  HKLM_Key,
241  NULL);
242  Status = NtOpenKey(&HKLM_Software_Key, KEY_READ, &ObjectAttributes);
244 
245  /* Get the name info length */
246  InfoLength = 0;
247  Status = NtQueryKey(HKLM_Software_Key, KeyNameInformation, NULL, 0, &InfoLength);
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);
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 
273 {
276 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
USHORT MaximumLength
Definition: env_spec_w32.h:370
static void Test_KeyNameInformation(void)
Definition: NtQueryKey.c:188
#define KEY_READ
Definition: nt_native.h:1023
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
NTSTATUS NTAPI NtQueryKey(IN HANDLE KeyHandle, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:632
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define UNICODE_NULL
#define ok(value,...)
smooth NULL
Definition: ftsmooth.c:416
#define ok_ntstatus(status, expected)
Definition: test.h:800
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
__wchar_t WCHAR
Definition: xmlstorage.h:180
LARGE_INTEGER LastWriteTime
Definition: nt_native.h:1117
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
static const WCHAR L[]
Definition: oid.c:1250
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define ok_size_t(expression, result)
Definition: test.h:780
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI NtDeleteKey(IN HANDLE KeyHandle)
Definition: ntapi.c:408
static void Test_KeyFullInformation(void)
Definition: NtQueryKey.c:13
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define skip(...)
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
unsigned int ULONG
Definition: retypes.h:1
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
START_TEST(NtQueryKey)
Definition: NtQueryKey.c:272
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
return STATUS_SUCCESS
Definition: btrfs.c:2745
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
LONGLONG QuadPart
Definition: typedefs.h:112
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14