652f8d4ab5a90cdea372ee43371744e72a825d82
[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 functions
7  * PROGRAMMERS:     Rex Jolliff
8  */
9
10 #include <ctype.h>
11
12 #include <ddk/ntddk.h>
13 #include <roscfg.h>
14 #include <internal/ob.h>
15 #include <limits.h>
16 #include <string.h>
17 #include <internal/pool.h>
18 #include <internal/registry.h>
19 #include <internal/ntoskrnl.h>
20
21 #define NDEBUG
22 #include <internal/debug.h>
23
24 #include "cm.h"
25
26 /* GLOBALS ******************************************************************/
27
28 static BOOLEAN CmiHardwareHiveImported = FALSE;
29
30 /* FUNCTIONS ****************************************************************/
31
32 static PCHAR 
33 checkAndSkipMagic (PCHAR  regChunk)
34 {
35   if (strncmp (regChunk, 
36                REGISTRY_FILE_MAGIC, 
37                strlen (REGISTRY_FILE_MAGIC)) != 0)
38   {
39     CPRINT ("incorrect magic number in registry chunk. expected: %s got:%.*s\n",
40             REGISTRY_FILE_MAGIC,
41             strlen (REGISTRY_FILE_MAGIC),
42             regChunk);
43     return  0;
44   }
45   regChunk += strlen (REGISTRY_FILE_MAGIC);
46   DPRINT ("Found regsitry chunk magic value\n");
47
48   return  regChunk;
49 }
50
51 static PCHAR
52 skipWhitespaceInChunk (PCHAR regChunk)
53 {
54   while (*regChunk && isspace (*regChunk))
55     regChunk++;
56
57   return *regChunk ? regChunk : 0;
58 }
59
60 static int
61 computeKeyNameSize (PCHAR  regChunk)
62 {
63   int  copyCount = 0;
64
65   while (*regChunk != 0 && *regChunk != ']')
66   {
67     copyCount++;
68     regChunk++;
69   }
70
71   return  copyCount;
72 }
73
74 static BOOLEAN
75 allocateKeyName (PUNICODE_STRING  newKeyName, int  newKeySize)
76 {
77   if (newKeyName->MaximumLength < (newKeySize + 1) * sizeof (WCHAR))
78   {
79     if (newKeyName->Buffer != 0)
80       ExFreePool (newKeyName->Buffer);
81     newKeyName->Length = 0;
82     newKeyName->MaximumLength = (newKeySize + 1) * sizeof (WCHAR);
83     newKeyName->Buffer = ExAllocatePool (NonPagedPool, newKeyName->MaximumLength);
84     if (newKeyName->Buffer == 0)
85     {
86       CPRINT ("Could not allocate space for key name\n");
87       return  FALSE;
88     }
89     newKeyName->Buffer [0] = 0;
90   }
91   else
92   {
93     newKeyName->Length = 0;
94     newKeyName->Buffer [0] = 0;
95   }
96
97   return  TRUE;
98 }
99
100 static PCHAR
101 skipToNextKeyInChunk (PCHAR  regChunk)
102 {
103   while (*regChunk != 0 && *regChunk != '[')
104   {
105     while (*regChunk != 0 && *regChunk != '\n')
106     {
107       regChunk++;
108     }
109     regChunk++;
110   }
111
112   return  *regChunk ? regChunk : 0;
113 }
114
115 static PCHAR
116 getKeyNameFromChunk (PCHAR  regChunk, PUNICODE_STRING  newKeyName)
117 {
118   int index = 0;
119
120   while (*regChunk != 0 && *regChunk != ']')
121   {
122     newKeyName->Buffer [index++] = *regChunk++;
123   }
124   newKeyName->Buffer [index] = '\0';
125   newKeyName->Length = index * sizeof (WCHAR);
126
127   return  *regChunk ? regChunk : 0;
128 }
129
130 static HANDLE
131 createNewKey (PUNICODE_STRING  newKeyName)
132 {
133   NTSTATUS  status;
134   OBJECT_ATTRIBUTES  attributes;
135   HANDLE  handleToReturn;
136
137   DPRINT ("Creating key (%wZ)\n", newKeyName);
138   InitializeObjectAttributes (&attributes,
139                               newKeyName,
140                               0,
141                               0,
142                               NULL);
143   status = NtCreateKey (&handleToReturn,
144                         KEY_ALL_ACCESS,
145                         &attributes,
146                         0,
147                         NULL,
148                         REG_OPTION_VOLATILE,
149                         NULL);
150   if (!NT_SUCCESS(status))
151   {
152     CPRINT ("Could not crete key (%wZ)\n", newKeyName);
153     return  INVALID_HANDLE_VALUE;
154   }
155
156   return  handleToReturn;
157 }
158
159 static PCHAR
160 skipToNextKeyValueInChunk (PCHAR  regChunk)
161 {
162   while (*regChunk != 0 && *regChunk != '\n')
163     regChunk++;
164   regChunk = skipWhitespaceInChunk (regChunk);
165   
166   return  regChunk;
167 }
168
169 static int
170 computeKeyValueNameSize (PCHAR  regChunk)
171 {
172   int size = 0;
173
174   if (*regChunk != '\"')
175     return  0;
176   regChunk++;
177   while (*regChunk != 0 && *regChunk != '\"')
178   {
179     size++;
180     regChunk++;
181   }
182
183   return  regChunk ? size : 0;
184 }
185
186 static PCHAR
187 getKeyValueNameFromChunk (PCHAR  regChunk, PUNICODE_STRING  newKeyName)
188 {
189   int  index = 0;
190
191   regChunk++;
192   while (*regChunk != 0 && *regChunk != '\"')
193   {
194     newKeyName->Buffer [index++] = *regChunk++;
195   }
196   newKeyName->Buffer [index] = '\0';
197   newKeyName->Length = index * sizeof (WCHAR);
198   regChunk++;
199
200   return  *regChunk ? regChunk : 0;
201 }
202
203 static PCHAR 
204 getKeyValueTypeFromChunk (PCHAR  regChunk, PCHAR  dataFormat, int *keyValueType)
205 {
206   if (*regChunk == '\"')
207   {
208     strcpy (dataFormat, "string");
209     *keyValueType = REG_SZ;
210   }
211   else if (strncmp (regChunk, "hex", 3) == 0)
212   {
213     strcpy (dataFormat, "hex");
214     regChunk += 3;
215     if (*regChunk == '(')
216     {
217       regChunk++;
218       *keyValueType = atoi (regChunk);
219       while (*regChunk != 0 && *regChunk != ')')
220         regChunk++;
221       regChunk++;
222     }
223     else
224       *keyValueType = REG_BINARY;
225     if (*regChunk == ':')
226       regChunk++;
227   }
228   else if (strncmp (regChunk, "dword", 5) == 0)
229   {
230     strcpy (dataFormat, "dword");
231     *keyValueType = REG_DWORD;
232     regChunk += 5;
233     if (*regChunk == ':')
234       regChunk++;
235   }
236   else if (strncmp (regChunk, "multi", 5) == 0)
237   {
238     strcpy (dataFormat, "multi");
239     *keyValueType = REG_MULTI_SZ;
240     regChunk += 5;
241     if (*regChunk == ':')
242       regChunk++;
243   }
244   else if (strncmp (regChunk, "expand", 6) == 0)
245   {
246     strcpy (dataFormat, "expand");
247     *keyValueType = REG_EXPAND_SZ;
248     regChunk += 6;
249     if (*regChunk == ':')
250       regChunk++;
251   }
252   else
253   {
254     UNIMPLEMENTED;
255   }
256
257   return  *regChunk ? regChunk : 0;
258 }
259
260 static int 
261 computeKeyValueDataSize (PCHAR  regChunk, PCHAR  dataFormat)
262 {
263   int  dataSize = 0;
264
265   if (strcmp (dataFormat, "string") == 0)
266   {
267     regChunk++;
268     while (*regChunk != 0 && *regChunk != '\"')
269     {
270       dataSize++;
271       dataSize++;
272       regChunk++;
273     }
274     dataSize++;
275     dataSize++;
276   }
277   else if (strcmp (dataFormat, "hex") == 0)
278   {
279     while (*regChunk != 0 && isxdigit(*regChunk))
280     {
281       regChunk++;
282       regChunk++;
283       dataSize++;
284       if (*regChunk == ',')
285       {
286         regChunk++;
287         if (*regChunk == '\\')
288         {
289           regChunk++;
290           regChunk = skipWhitespaceInChunk (regChunk);
291         }
292       }
293     }
294   }
295   else if (strcmp (dataFormat, "dword") == 0)
296   {
297     dataSize = sizeof(DWORD);
298     while (*regChunk != 0 && isxdigit(*regChunk))
299     {
300       regChunk++;
301     }
302   }
303   else if (strcmp (dataFormat, "multi") == 0)
304   {
305     while (*regChunk == '\"')
306     {
307       regChunk++;
308       while (*regChunk != 0 && *regChunk != '\"')
309       {
310         dataSize++;
311         dataSize++;
312         regChunk++;
313       }
314       regChunk++;
315       dataSize++;
316       dataSize++;
317       if (*regChunk == ',')
318       {
319         regChunk++;
320         regChunk = skipWhitespaceInChunk (regChunk);
321         if (*regChunk == '\\')
322         {
323           regChunk++;
324           regChunk = skipWhitespaceInChunk (regChunk);
325         }
326       }
327       else
328         break;
329     }
330     dataSize++;
331     dataSize++;
332   }
333   else if (strcmp (dataFormat, "expand") == 0)
334   {
335     regChunk++;
336     while (*regChunk != 0 && *regChunk != '\"')
337     {
338       dataSize++;
339       dataSize++;
340       regChunk++;
341     }
342     dataSize++;
343     dataSize++;
344   }
345   else
346   {
347     UNIMPLEMENTED;
348   }
349
350   return  dataSize;
351 }
352
353 static BOOLEAN
354 allocateDataBuffer (PVOID * data, int * dataBufferSize, int dataSize)
355 {
356   if (*dataBufferSize < dataSize)
357   {
358     if (*dataBufferSize > 0)
359       ExFreePool (*data);
360     *data = ExAllocatePool (NonPagedPool, dataSize);
361     *dataBufferSize = dataSize;
362   }
363
364   return  TRUE;
365 }
366
367 static PCHAR
368 getKeyValueDataFromChunk (PCHAR  regChunk, PCHAR  dataFormat, PCHAR data)
369 {
370   char  dataValue;
371   ULONG ulValue;
372   PWCHAR ptr;
373   
374   if (strcmp (dataFormat, "string") == 0)
375   {
376     /* convert quoted string to zero-terminated Unicode string */
377     ptr = (PWCHAR)data;
378     regChunk++;
379     while (*regChunk != 0 && *regChunk != '\"')
380     {
381       *ptr++ = (WCHAR)*regChunk++;
382     }
383     *ptr = 0;
384     regChunk++;
385   }
386   else if (strcmp (dataFormat, "hex") == 0)
387   {
388     while (*regChunk != 0 && isxdigit (*regChunk))
389     {
390       dataValue = (isdigit (*regChunk) ? *regChunk - '0' : 
391         tolower(*regChunk) - 'a' + 10) << 4;
392       regChunk++;
393       dataValue += (isdigit (*regChunk) ? *regChunk - '0' : 
394         tolower(*regChunk) - 'a' + 10);
395       regChunk++;
396       *data++ = dataValue;
397       if (*regChunk == ',')
398       {
399         regChunk++;
400         if (*regChunk == '\\')
401         {
402           regChunk++;
403           regChunk = skipWhitespaceInChunk (regChunk);
404         }
405       }
406     }
407   }
408   else if (strcmp (dataFormat, "dword") == 0)
409   {
410     ulValue = 0;
411     while (*regChunk != 0 && isxdigit(*regChunk))
412     {
413       dataValue = (isdigit (*regChunk) ? *regChunk - '0' : 
414         tolower(*regChunk) - 'a' + 10);
415       ulValue = (ulValue << 4) + dataValue;
416       regChunk++;
417     }
418     memcpy(data, &ulValue, sizeof(ULONG));
419   }
420   else if (strcmp (dataFormat, "multi") == 0)
421   {
422     ptr = (PWCHAR)data;
423     while (*regChunk == '\"')
424     {
425       regChunk++;
426       while (*regChunk != 0 && *regChunk != '\"')
427       {
428         *ptr++ = (WCHAR)*regChunk++;
429       }
430       regChunk++;
431       *ptr++ = 0;
432       if (*regChunk == ',')
433       {
434         regChunk++;
435         regChunk = skipWhitespaceInChunk (regChunk);
436         if (*regChunk == '\\')
437         {
438           regChunk++;
439           regChunk = skipWhitespaceInChunk (regChunk);
440         }
441       }
442       else
443         break;
444     }
445     *ptr = 0;
446   }
447   else if (strcmp (dataFormat, "expand") == 0)
448   {
449     /* convert quoted string to zero-terminated Unicode string */
450     ptr = (PWCHAR)data;
451     regChunk++;
452     while (*regChunk != 0 && *regChunk != '\"')
453     {
454       *ptr++ = (WCHAR)*regChunk++;
455     }
456     *ptr = 0;
457     regChunk++;
458   }
459   else
460   {
461     UNIMPLEMENTED;
462   }
463
464   return  *regChunk ? regChunk : 0;
465 }
466
467 static BOOLEAN
468 setKeyValue (HANDLE  currentKey,
469              PUNICODE_STRING  newValueName,
470              ULONG  keyValueType,
471              PVOID  data,
472              ULONG  dataSize)
473 {
474   NTSTATUS  status;
475
476   DPRINT ("Adding value (%wZ) to current key, with data type %d size %d\n",
477           newValueName,
478           keyValueType,
479           dataSize);
480   status = NtSetValueKey (currentKey,
481                           newValueName,
482                           0,
483                           keyValueType,
484                           data,
485                           dataSize);
486   if (!NT_SUCCESS(status))
487   {
488     CPRINT ("could not set key value, rc:%08x\n", status);
489     return  FALSE;
490   }
491
492   return  TRUE;
493 }
494
495 VOID
496 CmImportTextHive(PCHAR  ChunkBase,
497                  ULONG  ChunkSize)
498 {
499   HANDLE  currentKey = INVALID_HANDLE_VALUE;
500   int  newKeySize;
501   UNICODE_STRING  newKeyName = {0, 0, 0};
502   char  dataFormat [10];
503   int  keyValueType;
504   int  dataSize = 0;
505   int  dataBufferSize = 0;
506   PVOID  data = 0;
507   PCHAR regChunk;
508
509   DPRINT("ChunkBase %p  ChunkSize %lx\n", ChunkBase, ChunkSize);
510
511   regChunk = checkAndSkipMagic (ChunkBase);
512   if (regChunk == 0)
513     return;
514
515   while (regChunk != 0 && *regChunk != 0 && (((ULONG)regChunk-(ULONG)ChunkBase) < ChunkSize))
516   {
517     regChunk = skipWhitespaceInChunk (regChunk);
518     if (regChunk == 0)
519       continue;
520
521     if (*regChunk == '[')
522     {
523       if (currentKey != INVALID_HANDLE_VALUE)
524       {
525         DPRINT("Closing current key: 0x%lx\n", currentKey);
526         NtClose (currentKey);
527         currentKey = INVALID_HANDLE_VALUE;
528       }
529
530       regChunk++;
531
532       newKeySize = computeKeyNameSize (regChunk);
533       if (!allocateKeyName (&newKeyName, newKeySize))
534       {
535         regChunk = 0;
536         continue;
537       }
538
539       regChunk = getKeyNameFromChunk (regChunk, &newKeyName);
540       if (regChunk == 0)
541         continue;
542
543       currentKey = createNewKey (&newKeyName);
544       if (currentKey == INVALID_HANDLE_VALUE)
545       {
546         regChunk = skipToNextKeyInChunk (regChunk);
547         continue;
548       }
549
550       regChunk++;
551     }
552     else
553     {
554       if (currentKey == INVALID_HANDLE_VALUE)
555       {
556         regChunk = skipToNextKeyInChunk (regChunk);
557         continue;
558       }
559
560       newKeySize = computeKeyValueNameSize (regChunk);
561       if (!allocateKeyName (&newKeyName, newKeySize))
562       {
563         regChunk = 0;
564         continue;
565       }
566
567       regChunk = getKeyValueNameFromChunk (regChunk, &newKeyName);
568       if (regChunk == 0)
569         continue;
570
571       if (*regChunk != '=')
572       {
573         regChunk = skipToNextKeyValueInChunk (regChunk);
574         continue;
575       }
576       regChunk++;
577
578       regChunk = getKeyValueTypeFromChunk (regChunk, dataFormat, &keyValueType);
579       if (regChunk == 0)
580         continue;
581
582       dataSize = computeKeyValueDataSize (regChunk, dataFormat);
583       if (!allocateDataBuffer (&data, &dataBufferSize, dataSize))
584       {
585         regChunk = 0;
586         continue;
587       }
588       
589       regChunk = getKeyValueDataFromChunk (regChunk, dataFormat, data);
590       if (regChunk == 0)
591         continue;
592
593       if (!setKeyValue (currentKey, &newKeyName, keyValueType, data, dataSize))
594       {
595         regChunk = 0;
596         continue;
597       }
598     }
599   }
600
601   if (currentKey != INVALID_HANDLE_VALUE)
602   {
603     NtClose (currentKey);
604   }
605   if (newKeyName.Buffer != 0)
606   {
607     ExFreePool (newKeyName.Buffer);
608   }
609   if (data != 0)
610   {
611     ExFreePool (data);
612   }
613
614   return;
615 }
616
617
618 static BOOLEAN
619 CmImportBinaryHive (PCHAR ChunkBase,
620                     ULONG ChunkSize,
621                     ULONG Flags,
622                     PREGISTRY_HIVE *RegistryHive)
623 {
624   PREGISTRY_HIVE Hive;
625   PCELL_HEADER FreeBlock;
626   BLOCK_OFFSET BlockOffset;
627   PHBIN Bin;
628   ULONG i, j;
629   ULONG FreeOffset;
630   NTSTATUS Status;
631   ULONG BitmapSize;
632
633   *RegistryHive = NULL;
634
635   if (strncmp (ChunkBase, "regf", 4) != 0)
636     {
637       DPRINT1 ("Found invalid '%*s' magic\n", 4, ChunkBase);
638       return FALSE;
639     }
640
641   /* Create a new hive */
642   Hive = ExAllocatePool (NonPagedPool,
643                          sizeof(REGISTRY_HIVE));
644   if (Hive == NULL)
645     {
646       return FALSE;
647     }
648   RtlZeroMemory (Hive,
649                  sizeof(REGISTRY_HIVE));
650
651   /* Set hive flags */
652   Hive->Flags = Flags;
653
654   /* Allocate hive header */
655   Hive->HiveHeader = (PHIVE_HEADER)ExAllocatePool (NonPagedPool,
656                                                    sizeof(HIVE_HEADER));
657   if (Hive->HiveHeader == NULL)
658     {
659       DPRINT1 ("Allocating hive header failed\n");
660       ExFreePool (Hive);
661       return FALSE;
662     }
663
664   /* Import the hive header */
665   RtlCopyMemory (Hive->HiveHeader,
666                  ChunkBase,
667                  sizeof(HIVE_HEADER));
668
669   /* Read update counter */
670   Hive->UpdateCounter = Hive->HiveHeader->UpdateCounter1;
671
672   /* Set the hive's size */
673   Hive->FileSize = ChunkSize;
674
675   /* Set the size of the block list */
676   Hive->BlockListSize = (Hive->FileSize / 4096) - 1;
677
678   /* Allocate block list */
679   DPRINT("Space needed for block list describing hive: 0x%x\n",
680          sizeof(PHBIN *) * Hive->BlockListSize);
681   Hive->BlockList = ExAllocatePool (NonPagedPool,
682                                     sizeof(PHBIN *) * Hive->BlockListSize);
683   if (Hive->BlockList == NULL)
684     {
685       DPRINT1 ("Allocating block list failed\n");
686       ExFreePool (Hive->HiveHeader);
687       ExFreePool (Hive);
688       return FALSE;
689     }
690
691   /* Allocate the hive block */
692   Hive->BlockList[0] = ExAllocatePool (PagedPool,
693                                        Hive->FileSize - 4096);
694   if (Hive->BlockList[0] == NULL)
695     {
696       DPRINT1 ("Allocating the first hive block failed\n");
697       ExFreePool (Hive->BlockList);
698       ExFreePool (Hive->HiveHeader);
699       ExFreePool (Hive);
700       return FALSE;
701     }
702
703   /* Import the hive block */
704   RtlCopyMemory (Hive->BlockList[0],
705                  ChunkBase + 4096,
706                  Hive->FileSize - 4096);
707
708   /* Initialize the free block list */
709   Hive->FreeListSize = 0;
710   Hive->FreeListMax = 0;
711   Hive->FreeList = NULL;
712
713   BlockOffset = 0;
714   for (i = 0; i < Hive->BlockListSize; i++)
715     {
716       Hive->BlockList[i] = (PHBIN) (((ULONG_PTR)Hive->BlockList[0]) + BlockOffset);
717       Bin = (PHBIN) (((ULONG_PTR)Hive->BlockList[i]));
718       if (Bin->BlockId != REG_BIN_ID)
719         {
720           DPRINT1 ("Bad BlockId %x, offset %x\n", Bin->BlockId, BlockOffset);
721           /* FIXME: */
722           assert(FALSE);
723 //        return STATUS_INSUFFICIENT_RESOURCES;
724         }
725
726       assertmsg((Bin->BlockSize % 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", Bin->BlockSize));
727
728       if (Bin->BlockSize > 4096)
729         {
730           for (j = 1; j < Bin->BlockSize / 4096; j++)
731             {
732               Hive->BlockList[i + j] = Hive->BlockList[i];
733             }
734           i = i + j - 1;
735         }
736
737       /* Search free blocks and add to list */
738       FreeOffset = REG_HBIN_DATA_OFFSET;
739       while (FreeOffset < Bin->BlockSize)
740         {
741           FreeBlock = (PCELL_HEADER) ((ULONG_PTR)Hive->BlockList[i] + FreeOffset);
742           if (FreeBlock->CellSize > 0)
743             {
744               Status = CmiAddFree(Hive,
745                                   FreeBlock,
746                                   Hive->BlockList[i]->BlockOffset + FreeOffset,
747                                   FALSE);
748               if (!NT_SUCCESS(Status))
749                 {
750                   /* FIXME: */
751                   assert(FALSE);
752                 }
753
754               FreeOffset += FreeBlock->CellSize;
755             }
756           else
757             {
758               FreeOffset -= FreeBlock->CellSize;
759             }
760         }
761       BlockOffset += Bin->BlockSize;
762     }
763
764   if (!(Hive->Flags & HIVE_VOLATILE))
765     {
766       /* Calculate bitmap size in bytes (always a multiple of 32 bits) */
767       BitmapSize = ROUND_UP (Hive->BlockListSize, sizeof(ULONG) * 8) / 8;
768       DPRINT ("Hive->BlockListSize: %lu\n", Hive->BlockListSize);
769       DPRINT ("BitmapSize:  %lu Bytes  %lu Bits\n", BitmapSize, BitmapSize * 8);
770
771       /* Allocate bitmap */
772       Hive->BitmapBuffer = (PULONG)ExAllocatePool (PagedPool,
773                                                    BitmapSize);
774       if (Hive->BitmapBuffer == NULL)
775         {
776           DPRINT1 ("Allocating the hive bitmap failed\n");
777           ExFreePool (Hive->BlockList[0]);
778           ExFreePool (Hive->BlockList);
779           ExFreePool (Hive->HiveHeader);
780           ExFreePool (Hive);
781           return FALSE;
782         }
783
784       /* Initialize bitmap */
785       RtlInitializeBitMap (&Hive->DirtyBitMap,
786                            Hive->BitmapBuffer,
787                            BitmapSize * 8);
788       RtlClearAllBits (&Hive->DirtyBitMap);
789       Hive->HiveDirty = FALSE;
790     }
791
792   /* Initialize the hive's executive resource */
793   ExInitializeResourceLite(&Hive->HiveResource);
794
795   /* Acquire hive list lock exclusively */
796   ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
797
798   /* Add the new hive to the hive list */
799   InsertTailList(&CmiHiveListHead, &Hive->HiveList);
800
801   /* Release hive list lock */
802   ExReleaseResourceLite(&CmiHiveListLock);
803
804   *RegistryHive = Hive;
805
806   return TRUE;
807 }
808
809
810 BOOLEAN
811 CmImportSystemHive(PCHAR ChunkBase,
812                    ULONG ChunkSize)
813 {
814   PREGISTRY_HIVE RegistryHive;
815   UNICODE_STRING KeyName;
816   NTSTATUS Status;
817
818   DPRINT ("CmImportSystemHive() called\n");
819
820   if (strncmp (ChunkBase, "REGEDIT4", 8) == 0)
821     {
822       DPRINT ("Found 'REGEDIT4' magic\n");
823       CmImportTextHive (ChunkBase, ChunkSize);
824       return TRUE;
825     }
826   else if (strncmp (ChunkBase, "regf", 4) != 0)
827     {
828       DPRINT1 ("Found invalid '%.*s' magic\n", 4, ChunkBase);
829       return FALSE;
830     }
831
832   DPRINT ("Found '%.*s' magic\n", 4, ChunkBase);
833
834   /* Import the binary system hive (non-volatile, offset-based, permanent) */
835   if (!CmImportBinaryHive (ChunkBase, ChunkSize, 0, &RegistryHive))
836     {
837       DPRINT1 ("CmiImportBinaryHive() failed\n", Status);
838       return FALSE;
839     }
840
841   /* Attach it to the machine key */
842   RtlInitUnicodeString (&KeyName,
843                         L"\\Registry\\Machine\\System");
844   Status = CmiConnectHive (RegistryHive,
845                            &KeyName);
846   if (!NT_SUCCESS(Status))
847     {
848       DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
849 //      CmiRemoveRegistryHive(RegistryHive);
850       return FALSE;
851     }
852
853   /* Set the hive filename */
854   RtlCreateUnicodeString (&RegistryHive->HiveFileName,
855                           SYSTEM_REG_FILE);
856
857   /* Set the log filename */
858   RtlCreateUnicodeString (&RegistryHive->LogFileName,
859                           SYSTEM_LOG_FILE);
860
861   return TRUE;
862 }
863
864
865 BOOLEAN
866 CmImportHardwareHive(PCHAR ChunkBase,
867                      ULONG ChunkSize)
868 {
869   PREGISTRY_HIVE RegistryHive;
870   OBJECT_ATTRIBUTES ObjectAttributes;
871   UNICODE_STRING KeyName;
872   HANDLE HardwareKey;
873   ULONG Disposition;
874   NTSTATUS Status;
875
876   DPRINT ("CmImportHardwareHive() called\n");
877
878   if (CmiHardwareHiveImported == TRUE)
879     return TRUE;
880
881   if (ChunkBase == NULL &&
882       ChunkSize == 0)
883     {
884       /* Create '\Registry\Machine\HARDWARE' key. */
885       RtlInitUnicodeString(&KeyName,
886                            L"\\Registry\\Machine\\HARDWARE");
887       InitializeObjectAttributes (&ObjectAttributes,
888                                   &KeyName,
889                                   0,
890                                   NULL,
891                                   NULL);
892       Status = NtCreateKey (&HardwareKey,
893                             KEY_ALL_ACCESS,
894                             &ObjectAttributes,
895                             0,
896                             NULL,
897                             REG_OPTION_VOLATILE,
898                             &Disposition);
899       if (!NT_SUCCESS(Status))
900         {
901           return FALSE;
902         }
903       NtClose (HardwareKey);
904
905       /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
906       RtlInitUnicodeString(&KeyName,
907                            L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION");
908       InitializeObjectAttributes (&ObjectAttributes,
909                                   &KeyName,
910                                   0,
911                                   NULL,
912                                   NULL);
913       Status = NtCreateKey (&HardwareKey,
914                             KEY_ALL_ACCESS,
915                             &ObjectAttributes,
916                             0,
917                             NULL,
918                             REG_OPTION_VOLATILE,
919                             &Disposition);
920       if (!NT_SUCCESS(Status))
921         {
922           return FALSE;
923         }
924       NtClose (HardwareKey);
925
926       /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */
927       RtlInitUnicodeString(&KeyName,
928                            L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP");
929       InitializeObjectAttributes (&ObjectAttributes,
930                                   &KeyName,
931                                   0,
932                                   NULL,
933                                   NULL);
934       Status = NtCreateKey (&HardwareKey,
935                             KEY_ALL_ACCESS,
936                             &ObjectAttributes,
937                             0,
938                             NULL,
939                             REG_OPTION_VOLATILE,
940                             &Disposition);
941       if (!NT_SUCCESS(Status))
942         {
943           return FALSE;
944         }
945       NtClose (HardwareKey);
946
947       /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */
948       RtlInitUnicodeString(&KeyName,
949                            L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
950       InitializeObjectAttributes (&ObjectAttributes,
951                                   &KeyName,
952                                   0,
953                                   NULL,
954                                   NULL);
955       Status = NtCreateKey (&HardwareKey,
956                             KEY_ALL_ACCESS,
957                             &ObjectAttributes,
958                             0,
959                             NULL,
960                             REG_OPTION_VOLATILE,
961                             &Disposition);
962       if (!NT_SUCCESS(Status))
963         {
964           return FALSE;
965         }
966       NtClose (HardwareKey);
967
968       return TRUE;
969     }
970
971   if (strncmp (ChunkBase, "regf", 4) != 0)
972     {
973       DPRINT1 ("Found invalid '%.*s' magic\n", 4, ChunkBase);
974       return FALSE;
975     }
976
977   DPRINT ("Found '%.*s' magic\n", 4, ChunkBase);
978   DPRINT ("ChunkBase %lx  ChunkSize %lu\n", ChunkBase, ChunkSize);
979
980   /* Import the binary system hive (volatile, offset-based, permanent) */
981   if (!CmImportBinaryHive (ChunkBase, ChunkSize, HIVE_VOLATILE, &RegistryHive))
982     {
983       DPRINT1 ("CmiImportBinaryHive() failed\n", Status);
984       return FALSE;
985     }
986
987   /* Attach it to the machine key */
988   RtlInitUnicodeString (&KeyName,
989                         L"\\Registry\\Machine\\HARDWARE");
990   Status = CmiConnectHive (RegistryHive,
991                            &KeyName);
992   if (!NT_SUCCESS(Status))
993     {
994       DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
995 //      CmiRemoveRegistryHive(RegistryHive);
996       return FALSE;
997     }
998
999   /* Set the hive filename */
1000   RtlInitUnicodeString (&RegistryHive->HiveFileName,
1001                         NULL);
1002
1003   /* Set the log filename */
1004   RtlInitUnicodeString (&RegistryHive->LogFileName,
1005                         NULL);
1006
1007   CmiHardwareHiveImported = TRUE;
1008
1009   return TRUE;
1010 }
1011
1012 /* EOF */