- Fixed the freeing of memory from boot load drivers.
[reactos.git] / reactos / ntoskrnl / cm / import.c
1 /* $Id: import.c,v 1.23 2003/10/12 17:05:44 hbirr Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cm/import.c
6 * PURPOSE: Registry-Hive import functions
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 /* INCLUDES *****************************************************************/
11
12
13 #include <ddk/ntddk.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <roscfg.h>
17 #include <internal/ob.h>
18 #include <internal/pool.h>
19 #include <internal/registry.h>
20 #include <internal/ntoskrnl.h>
21
22 #define NDEBUG
23 #include <internal/debug.h>
24
25 #include "cm.h"
26
27 /* GLOBALS ******************************************************************/
28
29 static BOOLEAN CmiHardwareHiveImported = FALSE;
30
31
32 /* FUNCTIONS ****************************************************************/
33
34 static BOOLEAN
35 CmImportBinaryHive (PCHAR ChunkBase,
36 ULONG ChunkSize,
37 ULONG Flags,
38 PREGISTRY_HIVE *RegistryHive)
39 {
40 PREGISTRY_HIVE Hive;
41 NTSTATUS Status;
42
43 *RegistryHive = NULL;
44
45 if (strncmp (ChunkBase, "regf", 4))
46 {
47 DPRINT1 ("Found invalid '%*s' magic\n", 4, ChunkBase);
48 return FALSE;
49 }
50
51 /* Create a new hive */
52 Hive = ExAllocatePool (NonPagedPool,
53 sizeof(REGISTRY_HIVE));
54 if (Hive == NULL)
55 {
56 return FALSE;
57 }
58 RtlZeroMemory (Hive,
59 sizeof(REGISTRY_HIVE));
60
61 /* Set hive flags */
62 Hive->Flags = Flags;
63
64 /* Allocate hive header */
65 Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
66 sizeof(HIVE_HEADER));
67 if (Hive->HiveHeader == NULL)
68 {
69 DPRINT1 ("Allocating hive header failed\n");
70 ExFreePool (Hive);
71 return FALSE;
72 }
73
74 /* Import the hive header */
75 RtlCopyMemory (Hive->HiveHeader,
76 ChunkBase,
77 sizeof(HIVE_HEADER));
78
79 /* Read update counter */
80 Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1;
81
82 /* Set the hive's size */
83 Hive->FileSize = ChunkSize;
84
85 /* Set the size of the block list */
86 Hive->BlockListSize = (Hive->FileSize / 4096) - 1;
87
88 /* Allocate block list */
89 DPRINT("Space needed for block list describing hive: 0x%x\n",
90 Hive->BlockListSize * sizeof(PHBIN *));
91 Hive->BlockList = ExAllocatePool (NonPagedPool,
92 Hive->BlockListSize * sizeof(PHBIN *));
93 if (Hive->BlockList == NULL)
94 {
95 DPRINT1 ("Allocating block list failed\n");
96 ExFreePool (Hive->HiveHeader);
97 ExFreePool (Hive);
98 return FALSE;
99 }
100 RtlZeroMemory (Hive->BlockList,
101 Hive->BlockListSize * sizeof(PHBIN *));
102
103 /* Import the bins */
104 Status = CmiImportHiveBins(Hive,
105 (PUCHAR)((ULONG_PTR)ChunkBase + 4096));
106 if (!NT_SUCCESS(Status))
107 {
108 DPRINT1 ("CmiImportHiveBins() failed (Status %lx)\n", Status);
109 CmiFreeHiveBins (Hive);
110 ExFreePool (Hive->BlockList);
111 ExFreePool (Hive->HiveHeader);
112 ExFreePool (Hive);
113 return Status;
114 }
115
116 /* Initialize the free cell list */
117 Status = CmiCreateHiveFreeCellList (Hive);
118 if (!NT_SUCCESS(Status))
119 {
120 DPRINT1 ("CmiCreateHiveFreeCellList() failed (Status %lx)\n", Status);
121 CmiFreeHiveBins (Hive);
122 ExFreePool (Hive->BlockList);
123 ExFreePool (Hive->HiveHeader);
124 ExFreePool (Hive);
125
126 return Status;
127 }
128
129 if (!(Hive->Flags & HIVE_NO_FILE))
130 {
131 /* Create the block bitmap */
132 Status = CmiCreateHiveBitmap (Hive);
133 if (!NT_SUCCESS(Status))
134 {
135 DPRINT1 ("CmiCreateHiveBitmap() failed (Status %lx)\n", Status);
136 CmiFreeHiveFreeCellList (Hive);
137 CmiFreeHiveBins (Hive);
138 ExFreePool (Hive->BlockList);
139 ExFreePool (Hive->HiveHeader);
140 ExFreePool (Hive);
141
142 return Status;
143 }
144 }
145
146 /* Initialize the hive's executive resource */
147 ExInitializeResourceLite(&Hive->HiveResource);
148
149 /* Acquire hive list lock exclusively */
150 ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
151
152 /* Add the new hive to the hive list */
153 InsertTailList(&CmiHiveListHead, &Hive->HiveList);
154
155 /* Release hive list lock */
156 ExReleaseResourceLite(&CmiHiveListLock);
157
158 *RegistryHive = Hive;
159
160 return TRUE;
161 }
162
163
164 BOOLEAN INIT_FUNCTION
165 CmImportSystemHive(PCHAR ChunkBase,
166 ULONG ChunkSize)
167 {
168 OBJECT_ATTRIBUTES ObjectAttributes;
169 PREGISTRY_HIVE RegistryHive;
170 UNICODE_STRING KeyName;
171 NTSTATUS Status;
172
173 DPRINT ("CmImportSystemHive() called\n");
174
175 if (strncmp (ChunkBase, "regf", 4))
176 {
177 DPRINT1 ("Found invalid '%.*s' magic\n", 4, ChunkBase);
178 return FALSE;
179 }
180
181 DPRINT ("Found '%.*s' magic\n", 4, ChunkBase);
182
183 /* Import the binary system hive (non-volatile, offset-based, permanent) */
184 if (!CmImportBinaryHive (ChunkBase, ChunkSize, 0, &RegistryHive))
185 {
186 DPRINT1 ("CmiImportBinaryHive() failed\n", Status);
187 return FALSE;
188 }
189
190 /* Attach it to the machine key */
191 RtlInitUnicodeString (&KeyName,
192 L"\\Registry\\Machine\\System");
193 InitializeObjectAttributes (&ObjectAttributes,
194 &KeyName,
195 OBJ_CASE_INSENSITIVE,
196 NULL,
197 NULL);
198 Status = CmiConnectHive (&ObjectAttributes,
199 RegistryHive);
200 if (!NT_SUCCESS(Status))
201 {
202 DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
203 // CmiRemoveRegistryHive(RegistryHive);
204 return FALSE;
205 }
206
207 /* Set the hive filename */
208 RtlCreateUnicodeString (&RegistryHive->HiveFileName,
209 SYSTEM_REG_FILE);
210
211 /* Set the log filename */
212 RtlCreateUnicodeString (&RegistryHive->LogFileName,
213 SYSTEM_LOG_FILE);
214
215 return TRUE;
216 }
217
218
219 BOOLEAN INIT_FUNCTION
220 CmImportHardwareHive(PCHAR ChunkBase,
221 ULONG ChunkSize)
222 {
223 OBJECT_ATTRIBUTES ObjectAttributes;
224 PREGISTRY_HIVE RegistryHive;
225 UNICODE_STRING KeyName;
226 HANDLE HardwareKey;
227 ULONG Disposition;
228 NTSTATUS Status;
229
230 DPRINT ("CmImportHardwareHive() called\n");
231
232 if (CmiHardwareHiveImported == TRUE)
233 return TRUE;
234
235 if (ChunkBase == NULL &&
236 ChunkSize == 0)
237 {
238 /* Create '\Registry\Machine\HARDWARE' key. */
239 RtlInitUnicodeString (&KeyName,
240 L"\\Registry\\Machine\\HARDWARE");
241 InitializeObjectAttributes (&ObjectAttributes,
242 &KeyName,
243 OBJ_CASE_INSENSITIVE,
244 NULL,
245 NULL);
246 Status = NtCreateKey (&HardwareKey,
247 KEY_ALL_ACCESS,
248 &ObjectAttributes,
249 0,
250 NULL,
251 REG_OPTION_VOLATILE,
252 &Disposition);
253 if (!NT_SUCCESS(Status))
254 {
255 return FALSE;
256 }
257 NtClose (HardwareKey);
258
259 /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
260 RtlInitUnicodeString(&KeyName,
261 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION");
262 InitializeObjectAttributes (&ObjectAttributes,
263 &KeyName,
264 OBJ_CASE_INSENSITIVE,
265 NULL,
266 NULL);
267 Status = NtCreateKey (&HardwareKey,
268 KEY_ALL_ACCESS,
269 &ObjectAttributes,
270 0,
271 NULL,
272 REG_OPTION_VOLATILE,
273 &Disposition);
274 if (!NT_SUCCESS(Status))
275 {
276 return FALSE;
277 }
278 NtClose (HardwareKey);
279
280 /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */
281 RtlInitUnicodeString (&KeyName,
282 L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP");
283 InitializeObjectAttributes (&ObjectAttributes,
284 &KeyName,
285 OBJ_CASE_INSENSITIVE,
286 NULL,
287 NULL);
288 Status = NtCreateKey (&HardwareKey,
289 KEY_ALL_ACCESS,
290 &ObjectAttributes,
291 0,
292 NULL,
293 REG_OPTION_VOLATILE,
294 &Disposition);
295 if (!NT_SUCCESS(Status))
296 {
297 return FALSE;
298 }
299 NtClose (HardwareKey);
300
301 /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */
302 RtlInitUnicodeString(&KeyName,
303 L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
304 InitializeObjectAttributes (&ObjectAttributes,
305 &KeyName,
306 OBJ_CASE_INSENSITIVE,
307 NULL,
308 NULL);
309 Status = NtCreateKey (&HardwareKey,
310 KEY_ALL_ACCESS,
311 &ObjectAttributes,
312 0,
313 NULL,
314 REG_OPTION_VOLATILE,
315 &Disposition);
316 if (!NT_SUCCESS(Status))
317 {
318 return FALSE;
319 }
320 NtClose (HardwareKey);
321
322 return TRUE;
323 }
324
325 /* Check the hive magic */
326 if (strncmp (ChunkBase, "regf", 4))
327 {
328 DPRINT1 ("Found invalid '%.*s' magic\n", 4, ChunkBase);
329 return FALSE;
330 }
331
332 DPRINT ("Found '%.*s' magic\n", 4, ChunkBase);
333 DPRINT ("ChunkBase %lx ChunkSize %lu\n", ChunkBase, ChunkSize);
334
335 /* Import the binary system hive (volatile, offset-based, permanent) */
336 if (!CmImportBinaryHive (ChunkBase, ChunkSize, HIVE_NO_FILE, &RegistryHive))
337 {
338 DPRINT1 ("CmiImportBinaryHive() failed\n", Status);
339 return FALSE;
340 }
341
342 /* Attach it to the machine key */
343 RtlInitUnicodeString (&KeyName,
344 L"\\Registry\\Machine\\HARDWARE");
345 InitializeObjectAttributes (&ObjectAttributes,
346 &KeyName,
347 OBJ_CASE_INSENSITIVE,
348 NULL,
349 NULL);
350 Status = CmiConnectHive (&ObjectAttributes,
351 RegistryHive);
352 if (!NT_SUCCESS(Status))
353 {
354 DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
355 // CmiRemoveRegistryHive(RegistryHive);
356 return FALSE;
357 }
358
359 /* Set the hive filename */
360 RtlInitUnicodeString (&RegistryHive->HiveFileName,
361 NULL);
362
363 /* Set the log filename */
364 RtlInitUnicodeString (&RegistryHive->LogFileName,
365 NULL);
366
367 CmiHardwareHiveImported = TRUE;
368
369 return TRUE;
370 }
371
372 /* EOF */