[NTOS:CM] Check for correct status from ZwQueryObject. 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 POBJECT_NAME_INFORMATION FileNameInfo;
139
140 HivePath.Buffer = NULL;
141 FileNameInfo = NULL;
142
143 /* Create or open the hive list key */
144 InitializeObjectAttributes(&ObjectAttributes,
145 &HiveListValueName,
146 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
147 NULL,
148 NULL);
149 Status = ZwCreateKey(&KeyHandle,
150 KEY_READ | KEY_WRITE,
151 &ObjectAttributes,
152 0,
153 NULL,
154 REG_OPTION_VOLATILE,
155 NULL);
156 if (!NT_SUCCESS(Status))
157 {
158 /* Fail */
159 DPRINT1("CmpAddToHiveFileList: Creation or opening of the hive list failed, status = 0x%08lx\n", Status);
160 return Status;
161 }
162
163 /* Retrieve the name of the hive */
164 if (!CmpGetHiveName(Hive, &HivePath))
165 {
166 /* Fail */
167 DPRINT1("CmpAddToHiveFileList: Unable to retrieve the hive name\n");
168 Status = STATUS_NO_MEMORY;
169 goto Quickie;
170 }
171
172 /* Get the name of the corresponding file */
173 if (!(Hive->Hive.HiveFlags & HIVE_VOLATILE))
174 {
175 /* Determine the right buffer size and allocate */
176 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY],
177 ObjectNameInformation,
178 NULL,
179 0,
180 &Length);
181 if (Status != STATUS_INFO_LENGTH_MISMATCH)
182 {
183 DPRINT1("CmpAddToHiveFileList: Hive file name size query failed, status = 0x%08lx\n", Status);
184 goto Quickie;
185 }
186
187 FileNameInfo = ExAllocatePoolWithTag(PagedPool,
188 Length + sizeof(UNICODE_NULL),
189 TAG_CM);
190 if (FileNameInfo == NULL)
191 {
192 Status = STATUS_INSUFFICIENT_RESOURCES;
193 goto Quickie;
194 }
195
196 /* Try to get the value */
197 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY],
198 ObjectNameInformation,
199 FileNameInfo,
200 Length,
201 &Length);
202 if (NT_SUCCESS(Status))
203 {
204 /* Null-terminate and add the length of the terminator */
205 Length -= sizeof(OBJECT_NAME_INFORMATION);
206 FilePath = FileNameInfo->Name.Buffer;
207 FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL;
208 Length += sizeof(UNICODE_NULL);
209 }
210 else
211 {
212 /* Fail */
213 DPRINT1("CmpAddToHiveFileList: Hive file name query failed, status = 0x%08lx\n", Status);
214 goto Quickie;
215 }
216 }
217 else
218 {
219 /* No name */
220 FilePath = L"";
221 Length = sizeof(UNICODE_NULL);
222 }
223
224 /* Set the entry in the hive list */
225 Status = ZwSetValueKey(KeyHandle,
226 &HivePath,
227 0,
228 REG_SZ,
229 FilePath,
230 Length);
231 if (!NT_SUCCESS(Status))
232 {
233 /* Fail */
234 DPRINT1("CmpAddToHiveFileList: Setting of entry in the hive list failed, status = 0x%08lx\n", Status);
235 }
236
237 Quickie:
238 /* Cleanup and return status */
239 if (HivePath.Buffer)
240 {
241 ExFreePoolWithTag(HivePath.Buffer, TAG_CM);
242 }
243 if (FileNameInfo)
244 {
245 ExFreePoolWithTag(FileNameInfo, TAG_CM);
246 }
247 ObCloseHandle(KeyHandle, KernelMode);
248 return Status;
249 }
250
251 VOID
252 NTAPI
253 CmpRemoveFromHiveFileList(IN PCMHIVE Hive)
254 {
255 NTSTATUS Status;
256 OBJECT_ATTRIBUTES ObjectAttributes;
257 HANDLE KeyHandle;
258 UNICODE_STRING HivePath;
259
260 /* Open the hive list key */
261 InitializeObjectAttributes(&ObjectAttributes,
262 &HiveListValueName,
263 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
264 NULL,
265 NULL);
266 Status = ZwOpenKey(&KeyHandle,
267 KEY_READ | KEY_WRITE,
268 &ObjectAttributes);
269 if (!NT_SUCCESS(Status))
270 {
271 /* Fail */
272 DPRINT1("CmpRemoveFromHiveFileList: Opening of the hive list failed, status = 0x%08lx\n", Status);
273 return;
274 }
275
276 /* Get the hive path name */
277 CmpGetHiveName(Hive, &HivePath);
278
279 /* Delete the hive path name from the list */
280 ZwDeleteValueKey(KeyHandle, &HivePath);
281
282 /* Cleanup allocation and handle */
283 ExFreePoolWithTag(HivePath.Buffer, TAG_CM);
284 ObCloseHandle(KeyHandle, KernelMode);
285 }
286
287 /* EOF */