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