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