xref: /reactos/ntoskrnl/config/cmhvlist.c (revision 53221834)
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 */
289