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