xref: /reactos/ntoskrnl/config/cmhvlist.c (revision 5417742f)
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     UCHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
138     ULONG Length = sizeof(Buffer);
139     POBJECT_NAME_INFORMATION FileNameInfo = (POBJECT_NAME_INFORMATION)Buffer;
140 
141     HivePath.Buffer = 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         /* Try to get the value */
176         Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY],
177                                ObjectNameInformation,
178                                FileNameInfo,
179                                Length,
180                                &Length);
181         if (NT_SUCCESS(Status))
182         {
183             /* Null-terminate and add the length of the terminator */
184             Length -= sizeof(OBJECT_NAME_INFORMATION);
185             FilePath = FileNameInfo->Name.Buffer;
186             FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL;
187             Length += sizeof(UNICODE_NULL);
188         }
189         else
190         {
191             /* Fail */
192             DPRINT1("CmpAddToHiveFileList: Hive file name query failed, status = 0x%08lx\n", Status);
193             goto Quickie;
194         }
195     }
196     else
197     {
198         /* No name */
199         FilePath = L"";
200         Length = sizeof(UNICODE_NULL);
201     }
202 
203     /* Set the entry in the hive list */
204     Status = ZwSetValueKey(KeyHandle,
205                            &HivePath,
206                            0,
207                            REG_SZ,
208                            FilePath,
209                            Length);
210     if (!NT_SUCCESS(Status))
211     {
212         /* Fail */
213         DPRINT1("CmpAddToHiveFileList: Setting of entry in the hive list failed, status = 0x%08lx\n", Status);
214     }
215 
216 Quickie:
217     /* Cleanup and return status */
218     if (HivePath.Buffer) ExFreePoolWithTag(HivePath.Buffer, TAG_CM);
219     ObCloseHandle(KeyHandle, KernelMode);
220     return Status;
221 }
222 
223 VOID
224 NTAPI
225 CmpRemoveFromHiveFileList(IN PCMHIVE Hive)
226 {
227     NTSTATUS Status;
228     OBJECT_ATTRIBUTES ObjectAttributes;
229     HANDLE KeyHandle;
230     UNICODE_STRING HivePath;
231 
232     /* Open the hive list key */
233     InitializeObjectAttributes(&ObjectAttributes,
234                                &HiveListValueName,
235                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
236                                NULL,
237                                NULL);
238     Status = ZwOpenKey(&KeyHandle,
239                        KEY_READ | KEY_WRITE,
240                        &ObjectAttributes);
241     if (!NT_SUCCESS(Status))
242     {
243         /* Fail */
244         DPRINT1("CmpRemoveFromHiveFileList: Opening of the hive list failed, status = 0x%08lx\n", Status);
245         return;
246     }
247 
248     /* Get the hive path name */
249     CmpGetHiveName(Hive, &HivePath);
250 
251     /* Delete the hive path name from the list */
252     ZwDeleteValueKey(KeyHandle, &HivePath);
253 
254     /* Cleanup allocation and handle */
255     ExFreePoolWithTag(HivePath.Buffer, TAG_CM);
256     ObCloseHandle(KeyHandle, KernelMode);
257 }
258 
259 /* EOF */
260