[NDK][NTOS] Add global definition of INIT_FUNCTION/INIT_SECTION (#779)
[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 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 */