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