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