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