[NTOS:CM] Do not call ZwQueryObject with a zero-size buffer. CORE-15882
[reactos.git] / ntoskrnl / config / cmhvlist.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmhvlist.c
5 * PURPOSE: Configuration Manager - Hives file list management
6 * PROGRAMMERS: Hermes BELUSCA - MAITO
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "ntoskrnl.h"
12 #define NDEBUG
13 #include "debug.h"
14
15 /* GLOBALS ********************************************************************/
16
17 UNICODE_STRING HiveListValueName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\hivelist");
18
19 /* FUNCTIONS ******************************************************************/
20
21 /* Note: the caller is expected to free the HiveName string buffer */
22 BOOLEAN
23 NTAPI
24 CmpGetHiveName(IN PCMHIVE Hive,
25 OUT PUNICODE_STRING HiveName)
26 {
27 HCELL_INDEX RootCell, LinkCell;
28 PCELL_DATA RootData, LinkData, ParentData;
29 ULONG ParentNameSize, LinkNameSize;
30 SIZE_T NameSize;
31 PWCHAR p;
32 UNICODE_STRING RegistryName = RTL_CONSTANT_STRING(L"\\REGISTRY\\");
33
34 /* Get the root cell of this hive */
35 RootCell = Hive->Hive.BaseBlock->RootCell;
36 RootData = HvGetCell(&Hive->Hive, RootCell);
37 if (!RootData) return FALSE;
38
39 /* Get the cell index at which this hive is linked to, and its parent */
40 LinkCell = RootData->u.KeyNode.Parent;
41 HvReleaseCell(&Hive->Hive, RootCell);
42
43 /* Sanity check */
44 ASSERT((&CmiVolatileHive->Hive)->ReleaseCellRoutine == NULL);
45
46 /* Get the cell data for link and parent */
47 LinkData = HvGetCell(&CmiVolatileHive->Hive, LinkCell);
48 if (!LinkData) return FALSE;
49 ParentData = HvGetCell(&CmiVolatileHive->Hive, LinkData->u.KeyNode.Parent);
50 if (!ParentData) return FALSE;
51
52 /* Get the size of the parent name */
53 if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME)
54 {
55 ParentNameSize = CmpCompressedNameSize(ParentData->u.KeyNode.Name,
56 ParentData->u.KeyNode.NameLength);
57 }
58 else
59 {
60 ParentNameSize = ParentData->u.KeyNode.NameLength;
61 }
62
63 /* Get the size of the link name */
64 if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME)
65 {
66 LinkNameSize = CmpCompressedNameSize(LinkData->u.KeyNode.Name,
67 LinkData->u.KeyNode.NameLength);
68 }
69 else
70 {
71 LinkNameSize = LinkData->u.KeyNode.NameLength;
72 }
73
74 /* No need to account for terminal NULL character since we deal with counted UNICODE strings */
75 NameSize = RegistryName.Length + ParentNameSize + sizeof(WCHAR) + LinkNameSize;
76
77 /* Allocate the memory */
78 HiveName->Buffer = ExAllocatePoolWithTag(PagedPool, NameSize, TAG_CM);
79 if (!HiveName->Buffer)
80 {
81 /* Fail */
82 DPRINT1("CmpGetHiveName: Unable to allocate memory\n");
83 return FALSE;
84 }
85
86 /* Build the string for it */
87 HiveName->Length = HiveName->MaximumLength = (USHORT)NameSize;
88 p = HiveName->Buffer;
89
90 /* Copy the parent name */
91 RtlCopyMemory(p, RegistryName.Buffer, RegistryName.Length);
92 p += RegistryName.Length / sizeof(WCHAR);
93 if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME)
94 {
95 CmpCopyCompressedName(p,
96 ParentNameSize,
97 ParentData->u.KeyNode.Name,
98 ParentData->u.KeyNode.NameLength);
99 }
100 else
101 {
102 RtlCopyMemory(p, ParentData->u.KeyNode.Name, ParentNameSize);
103 }
104
105 /* Add a path separator between parent and link */
106 p += ParentNameSize / sizeof(WCHAR);
107 *p = OBJ_NAME_PATH_SEPARATOR;
108 ++p;
109
110 /* Now copy the link name */
111 if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME)
112 {
113 CmpCopyCompressedName(p,
114 LinkNameSize,
115 LinkData->u.KeyNode.Name,
116 LinkData->u.KeyNode.NameLength);
117
118 }
119 else
120 {
121 RtlCopyMemory(p, LinkData->u.KeyNode.Name, LinkNameSize);
122 }
123
124 /* All done */
125 return TRUE;
126 }
127
128 NTSTATUS
129 NTAPI
130 CmpAddToHiveFileList(IN PCMHIVE Hive)
131 {
132 NTSTATUS Status;
133 OBJECT_ATTRIBUTES ObjectAttributes;
134 HANDLE KeyHandle;
135 UNICODE_STRING HivePath;
136 PWCHAR FilePath;
137 ULONG Length;
138 OBJECT_NAME_INFORMATION DummyNameInfo;
139 POBJECT_NAME_INFORMATION FileNameInfo;
140
141 HivePath.Buffer = NULL;
142 FileNameInfo = NULL;
143
144 /* Create or open the hive list key */
145 InitializeObjectAttributes(&ObjectAttributes,
146 &HiveListValueName,
147 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
148 NULL,
149 NULL);
150 Status = ZwCreateKey(&KeyHandle,
151 KEY_READ | KEY_WRITE,
152 &ObjectAttributes,
153 0,
154 NULL,
155 REG_OPTION_VOLATILE,
156 NULL);
157 if (!NT_SUCCESS(Status))
158 {
159 /* Fail */
160 DPRINT1("CmpAddToHiveFileList: Creation or opening of the hive list failed, status = 0x%08lx\n", Status);
161 return Status;
162 }
163
164 /* Retrieve the name of the hive */
165 if (!CmpGetHiveName(Hive, &HivePath))
166 {
167 /* Fail */
168 DPRINT1("CmpAddToHiveFileList: Unable to retrieve the hive name\n");
169 Status = STATUS_NO_MEMORY;
170 goto Quickie;
171 }
172
173 /* Get the name of the corresponding file */
174 if (!(Hive->Hive.HiveFlags & HIVE_VOLATILE))
175 {
176 /* Determine the right buffer size and allocate */
177 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY],
178 ObjectNameInformation,
179 &DummyNameInfo,
180 sizeof(DummyNameInfo),
181 &Length);
182 if (Status != STATUS_BUFFER_OVERFLOW)
183 {
184 DPRINT1("CmpAddToHiveFileList: Hive file name size query failed, status = 0x%08lx\n", Status);
185 goto Quickie;
186 }
187
188 FileNameInfo = ExAllocatePoolWithTag(PagedPool,
189 Length + sizeof(UNICODE_NULL),
190 TAG_CM);
191 if (FileNameInfo == NULL)
192 {
193 Status = STATUS_INSUFFICIENT_RESOURCES;
194 goto Quickie;
195 }
196
197 /* Try to get the value */
198 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY],
199 ObjectNameInformation,
200 FileNameInfo,
201 Length,
202 &Length);
203 if (NT_SUCCESS(Status))
204 {
205 /* Null-terminate and add the length of the terminator */
206 Length -= sizeof(OBJECT_NAME_INFORMATION);
207 FilePath = FileNameInfo->Name.Buffer;
208 FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL;
209 Length += sizeof(UNICODE_NULL);
210 }
211 else
212 {
213 /* Fail */
214 DPRINT1("CmpAddToHiveFileList: Hive file name query failed, status = 0x%08lx\n", Status);
215 goto Quickie;
216 }
217 }
218 else
219 {
220 /* No name */
221 FilePath = L"";
222 Length = sizeof(UNICODE_NULL);
223 }
224
225 /* Set the entry in the hive list */
226 Status = ZwSetValueKey(KeyHandle,
227 &HivePath,
228 0,
229 REG_SZ,
230 FilePath,
231 Length);
232 if (!NT_SUCCESS(Status))
233 {
234 /* Fail */
235 DPRINT1("CmpAddToHiveFileList: Setting of entry in the hive list failed, status = 0x%08lx\n", Status);
236 }
237
238 Quickie:
239 /* Cleanup and return status */
240 if (HivePath.Buffer)
241 {
242 ExFreePoolWithTag(HivePath.Buffer, TAG_CM);
243 }
244 if (FileNameInfo)
245 {
246 ExFreePoolWithTag(FileNameInfo, TAG_CM);
247 }
248 ObCloseHandle(KeyHandle, KernelMode);
249 return Status;
250 }
251
252 VOID
253 NTAPI
254 CmpRemoveFromHiveFileList(IN PCMHIVE Hive)
255 {
256 NTSTATUS Status;
257 OBJECT_ATTRIBUTES ObjectAttributes;
258 HANDLE KeyHandle;
259 UNICODE_STRING HivePath;
260
261 /* Open the hive list key */
262 InitializeObjectAttributes(&ObjectAttributes,
263 &HiveListValueName,
264 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
265 NULL,
266 NULL);
267 Status = ZwOpenKey(&KeyHandle,
268 KEY_READ | KEY_WRITE,
269 &ObjectAttributes);
270 if (!NT_SUCCESS(Status))
271 {
272 /* Fail */
273 DPRINT1("CmpRemoveFromHiveFileList: Opening of the hive list failed, status = 0x%08lx\n", Status);
274 return;
275 }
276
277 /* Get the hive path name */
278 CmpGetHiveName(Hive, &HivePath);
279
280 /* Delete the hive path name from the list */
281 ZwDeleteValueKey(KeyHandle, &HivePath);
282
283 /* Cleanup allocation and handle */
284 ExFreePoolWithTag(HivePath.Buffer, TAG_CM);
285 ObCloseHandle(KeyHandle, KernelMode);
286 }
287
288 /* EOF */