ReactOS 0.4.16-dev-981-g80eb313
registry.c
Go to the documentation of this file.
1/*
2 * FreeLoader
3 *
4 * Copyright (C) 2014 Timo Kreuzer <timo.kreuzer@reactos.org>
5 * 2022 George Bișoc <george.bisoc@reactos.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22#include <freeldr.h>
23#include <cmlib.h>
24#include "registry.h"
25#include <internal/cmboot.h>
26
27#include <debug.h>
29
32
35
36#define HCI_TO_HKEY(CellIndex) ((HKEY)(ULONG_PTR)(CellIndex))
37#ifndef HKEY_TO_HCI // See also registry.h
38#define HKEY_TO_HCI(hKey) ((HCELL_INDEX)(ULONG_PTR)(hKey))
39#endif
40
41#define GET_HHIVE(CmHive) (&((CmHive)->Hive))
42#define GET_HHIVE_FROM_HKEY(hKey) GET_HHIVE(CmSystemHive)
43#define GET_CM_KEY_NODE(hHive, hKey) ((PCM_KEY_NODE)HvGetCell(hHive, HKEY_TO_HCI(hKey)))
44
45#define GET_HBASE_BLOCK(ChunkBase) ((PHBASE_BLOCK)ChunkBase)
46
51 IN BOOLEAN Paged,
52 IN ULONG Tag)
53{
55 return FrLdrHeapAlloc(Size, Tag);
56}
57
58VOID
61 IN PVOID Ptr,
62 IN ULONG Quota)
63{
66}
67
94static
97 _In_ PCMHIVE CmHive,
98 _In_ PVOID ChunkBase,
99 _In_ BOOLEAN LoadAlternate)
100{
102 CM_CHECK_REGISTRY_STATUS CmStatusCode;
103
104 /* Initialize the hive */
105 Status = HvInitialize(GET_HHIVE(CmHive),
106 HINIT_FLAT, // HINIT_MEMORY_INPLACE
107 0,
109 ChunkBase,
111 CmpFree,
112 NULL,
113 NULL,
114 NULL,
115 NULL,
116 1,
117 NULL);
118 if (!NT_SUCCESS(Status))
119 {
120 ERR("Failed to initialize the flat hive (Status 0x%lx)\n", Status);
121 return FALSE;
122 }
123
124 /* Now check the hive and purge volatile data */
126 if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode))
127 {
128 ERR("CmCheckRegistry detected problems with the loaded flat hive (check code %lu)\n", CmStatusCode);
129 return FALSE;
130 }
131
132 return TRUE;
133}
134
168static
171 _In_ PCSTR DirectoryPath,
172 _In_ ULONG LogFileOffset,
173 _In_ PCSTR LogName,
174 _Out_ PVOID *LogData)
175{
177 ULONG LogId;
178 CHAR LogPath[MAX_PATH];
179 ULONG LogFileSize;
183 PVOID LogDataVirtual;
184 PVOID LogDataPhysical;
185
186 /* Build the full path to the hive log */
187 RtlStringCbCopyA(LogPath, sizeof(LogPath), DirectoryPath);
188 RtlStringCbCatA(LogPath, sizeof(LogPath), LogName);
189
190 /* Open the file */
191 Status = ArcOpen(LogPath, OpenReadOnly, &LogId);
192 if (Status != ESUCCESS)
193 {
194 ERR("Failed to open %s (ARC code %lu)\n", LogName, Status);
195 return FALSE;
196 }
197
198 /* Get the file length */
200 if (Status != ESUCCESS)
201 {
202 ERR("Failed to get file information from %s (ARC code %lu)\n", LogName, Status);
203 ArcClose(LogId);
204 return FALSE;
205 }
206
207 /* Capture the size of the hive log file */
208 LogFileSize = FileInfo.EndingAddress.LowPart;
209 if (LogFileSize == 0)
210 {
211 ERR("LogFileSize is 0, %s is corrupt\n", LogName);
212 ArcClose(LogId);
213 return FALSE;
214 }
215
216 /* Allocate memory blocks for our log data */
217 LogDataPhysical = MmAllocateMemoryWithType(
218 MM_SIZE_TO_PAGES(LogFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT,
220 if (LogDataPhysical == NULL)
221 {
222 ERR("Failed to allocate memory for log data\n");
223 ArcClose(LogId);
224 return FALSE;
225 }
226
227 /* Convert the address to virtual so that it can be useable */
228 LogDataVirtual = PaToVa(LogDataPhysical);
229
230 /* Seek within the log file at desired position */
231 Position.QuadPart = LogFileOffset;
233 if (Status != ESUCCESS)
234 {
235 ERR("Failed to seek at %s (ARC code %lu)\n", LogName, Status);
236 ArcClose(LogId);
237 return FALSE;
238 }
239
240 /* And read the actual data from the log */
241 Status = ArcRead(LogId, LogDataPhysical, LogFileSize, &BytesRead);
242 if (Status != ESUCCESS)
243 {
244 ERR("Failed to read %s (ARC code %lu)\n", LogName, Status);
245 ArcClose(LogId);
246 return FALSE;
247 }
248
249 *LogData = LogDataVirtual;
250 ArcClose(LogId);
251 return TRUE;
252}
253
275static
278 _Inout_ PVOID ChunkBase,
279 _In_ PCSTR DirectoryPath,
280 _In_ PCSTR LogName)
281{
283 CHAR FullLogFileName[MAX_PATH];
284 PVOID LogData;
285 PHBASE_BLOCK HiveBaseBlock;
286 PHBASE_BLOCK LogBaseBlock;
287
288 /* Build the complete path of the hive log */
289 RtlStringCbCopyA(FullLogFileName, sizeof(FullLogFileName), LogName);
290 RtlStringCbCatA(FullLogFileName, sizeof(FullLogFileName), ".LOG");
291 Success = RegLoadHiveLog(DirectoryPath, 0, FullLogFileName, &LogData);
292 if (!Success)
293 {
294 ERR("Failed to read the hive log\n");
295 return FALSE;
296 }
297
298 /* Make sure the header from the hive log is actually sane */
299 LogData = VaToPa(LogData);
300 LogBaseBlock = GET_HBASE_BLOCK(LogData);
301 if (!HvpVerifyHiveHeader(LogBaseBlock, HFILE_TYPE_LOG))
302 {
303 ERR("The hive log has corrupt base block\n");
304 return FALSE;
305 }
306
307 /* Copy the healthy header base block into the primary hive */
308 HiveBaseBlock = GET_HBASE_BLOCK(ChunkBase);
309 WARN("Recovering the hive base block...\n");
310 RtlCopyMemory(HiveBaseBlock,
311 LogBaseBlock,
312 LogBaseBlock->Cluster * HSECTOR_SIZE);
313 HiveBaseBlock->Type = HFILE_TYPE_PRIMARY;
314 return TRUE;
315}
316
348static
351 _Inout_ PVOID ChunkBase,
352 _In_ PCSTR DirectoryPath,
353 _In_ PCSTR LogName)
354{
356 ULONG StorageLength;
357 ULONG BlockIndex, LogIndex;
358 PUCHAR BlockPtr, BlockDest;
359 CHAR FullLogFileName[MAX_PATH];
360 PVOID LogData;
361 PUCHAR LogDataPhysical;
362 PHBASE_BLOCK HiveBaseBlock;
363
364 /* Build the complete path of the hive log */
365 RtlStringCbCopyA(FullLogFileName, sizeof(FullLogFileName), LogName);
366 RtlStringCbCatA(FullLogFileName, sizeof(FullLogFileName), ".LOG");
367 Success = RegLoadHiveLog(DirectoryPath, HV_LOG_HEADER_SIZE, FullLogFileName, &LogData);
368 if (!Success)
369 {
370 ERR("Failed to read the hive log\n");
371 return FALSE;
372 }
373
374 /* Make sure the dirty vector signature is there otherwise the hive log is corrupt */
375 LogDataPhysical = (PUCHAR)VaToPa(LogData);
376 if (*((PULONG)LogDataPhysical) != HV_LOG_DIRTY_SIGNATURE)
377 {
378 ERR("The hive log dirty signature could not be found\n");
379 return FALSE;
380 }
381
382 /* Copy the dirty data into the primary hive */
383 LogIndex = 0;
384 BlockIndex = 0;
385 HiveBaseBlock = GET_HBASE_BLOCK(ChunkBase);
386 StorageLength = HiveBaseBlock->Length / HBLOCK_SIZE;
387 for (; BlockIndex < StorageLength; ++BlockIndex)
388 {
389 /* Skip this block if it's not dirty and go to the next one */
390 if (LogDataPhysical[BlockIndex + sizeof(HV_LOG_DIRTY_SIGNATURE)] != HV_LOG_DIRTY_BLOCK)
391 {
392 continue;
393 }
394
395 /* Read the dirty block and copy it at right offsets */
396 BlockPtr = (PUCHAR)((ULONG_PTR)LogDataPhysical + 2 * HSECTOR_SIZE + LogIndex * HBLOCK_SIZE);
397 BlockDest = (PUCHAR)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HBLOCK_SIZE);
398 RtlCopyMemory(BlockDest, BlockPtr, HBLOCK_SIZE);
399
400 /* Increment the index in log as we continue further */
401 LogIndex++;
402 }
403
404 /* Fix the secondary sequence of the primary hive and compute a new checksum */
405 HiveBaseBlock->Sequence2 = HiveBaseBlock->Sequence1;
406 HiveBaseBlock->CheckSum = HvpHiveHeaderChecksum(HiveBaseBlock);
407 return TRUE;
408}
409
437 _In_ PVOID ChunkBase,
440 _In_ BOOLEAN LoadAlternate)
441{
443 PCM_KEY_NODE KeyNode;
444
445 TRACE("RegImportBinaryHive(%p, 0x%lx)\n", ChunkBase, ChunkSize);
446
447 /* Assume that we don't need boot recover, unless we have to */
448 ((PHBASE_BLOCK)ChunkBase)->BootRecover = HBOOT_NO_BOOT_RECOVER;
449
450 /* Allocate and initialize the hive */
451 CmSystemHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
452 Success = RegInitializeHive(CmSystemHive, ChunkBase, LoadAlternate);
453 if (!Success)
454 {
455 /* Free the buffer and retry again */
458
459 if (!RegRecoverHeaderHive(ChunkBase, SearchPath, "SYSTEM"))
460 {
461 ERR("Failed to recover the hive header block\n");
462 return FALSE;
463 }
464
465 if (!RegRecoverDataHive(ChunkBase, SearchPath, "SYSTEM"))
466 {
467 ERR("Failed to recover the hive data\n");
468 return FALSE;
469 }
470
471 /* Now retry initializing the hive again */
472 CmSystemHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
473 Success = RegInitializeHive(CmSystemHive, ChunkBase, LoadAlternate);
474 if (!Success)
475 {
476 ERR("Corrupted hive (despite recovery) %p\n", ChunkBase);
478 return FALSE;
479 }
480
481 /*
482 * Acknowledge the kernel we recovered the SYSTEM hive
483 * on our side by applying log data.
484 */
485 ((PHBASE_BLOCK)ChunkBase)->BootRecover = HBOOT_BOOT_RECOVERED_BY_HIVE_LOG;
486 }
487
488 /* Save the root key node */
492
493 /* Verify it is accessible */
495 ASSERT(KeyNode);
498
499 return TRUE;
500}
501
504 _In_ BOOLEAN LastKnownGood)
505{
506 UNICODE_STRING ControlSetName;
507 HCELL_INDEX ControlCell;
508 PCM_KEY_NODE KeyNode;
509 BOOLEAN AutoSelect;
510
511 TRACE("RegInitCurrentControlSet\n");
512
513 /* Choose which control set to open and set it as the new "Current" */
514 RtlInitUnicodeString(&ControlSetName,
515 LastKnownGood ? L"LastKnownGood"
516 : L"Default");
517
518 ControlCell = CmpFindControlSet(SystemHive,
520 &ControlSetName,
521 &AutoSelect);
522 if (ControlCell == HCELL_NIL)
523 {
524 ERR("CmpFindControlSet('%wZ') failed\n", &ControlSetName);
525 return FALSE;
526 }
527
528 CurrentControlSetKey = HCI_TO_HKEY(ControlCell);
529
530 /* Verify it is accessible */
531 KeyNode = (PCM_KEY_NODE)HvGetCell(SystemHive, ControlCell);
532 ASSERT(KeyNode);
534 HvReleaseCell(SystemHive, ControlCell);
535
536 return TRUE;
537}
538
539static
542 _Out_ PUNICODE_STRING NextElement,
543 _Inout_ PUNICODE_STRING RemainingPath)
544{
545 /* Check if there are any characters left */
546 if (RemainingPath->Length < sizeof(WCHAR))
547 {
548 /* Nothing left, bail out early */
549 return FALSE;
550 }
551
552 /* The next path elements starts with the remaining path */
553 NextElement->Buffer = RemainingPath->Buffer;
554
555 /* Loop until the path element ends */
556 while ((RemainingPath->Length >= sizeof(WCHAR)) &&
557 (RemainingPath->Buffer[0] != '\\'))
558 {
559 /* Skip this character */
560 RemainingPath->Buffer++;
561 RemainingPath->Length -= sizeof(WCHAR);
562 }
563
564 NextElement->Length = (USHORT)(RemainingPath->Buffer - NextElement->Buffer) * sizeof(WCHAR);
565 NextElement->MaximumLength = NextElement->Length;
566
567 /* Check if the path element ended with a path separator */
568 if (RemainingPath->Length >= sizeof(WCHAR))
569 {
570 /* Skip the path separator */
571 ASSERT(RemainingPath->Buffer[0] == '\\');
572 RemainingPath->Buffer++;
573 RemainingPath->Length -= sizeof(WCHAR);
574 }
575
576 /* Return whether we got any characters */
577 return TRUE;
578}
579
580#if 0
581LONG
583 _In_ HKEY Key,
586 _Inout_ PULONG NameSize,
587 _Out_opt_ PHKEY SubKey)
588{
590 PCM_KEY_NODE KeyNode, SubKeyNode;
591 HCELL_INDEX CellIndex;
592 USHORT NameLength;
593
594 TRACE("RegEnumKey(%p, %lu, %p, %p->%u)\n",
595 Key, Index, Name, NameSize, NameSize ? *NameSize : 0);
596
597 /* Get the key node */
598 KeyNode = GET_CM_KEY_NODE(Hive, Key);
599 ASSERT(KeyNode);
601
602 CellIndex = CmpFindSubKeyByNumber(Hive, KeyNode, Index);
603 if (CellIndex == HCELL_NIL)
604 {
605 TRACE("RegEnumKey index out of bounds (%d) in key (%.*s)\n",
606 Index, KeyNode->NameLength, KeyNode->Name);
608 return ERROR_NO_MORE_ITEMS;
609 }
611
612 /* Get the value cell */
613 SubKeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
614 ASSERT(SubKeyNode != NULL);
615 ASSERT(SubKeyNode->Signature == CM_KEY_NODE_SIGNATURE);
616
617 if (SubKeyNode->Flags & KEY_COMP_NAME)
618 {
619 NameLength = CmpCompressedNameSize(SubKeyNode->Name, SubKeyNode->NameLength);
620
621 /* Compressed name */
623 *NameSize,
624 SubKeyNode->Name,
625 SubKeyNode->NameLength);
626 }
627 else
628 {
629 NameLength = SubKeyNode->NameLength;
630
631 /* Normal name */
632 RtlCopyMemory(Name, SubKeyNode->Name,
633 min(*NameSize, SubKeyNode->NameLength));
634 }
635
636 if (*NameSize >= NameLength + sizeof(WCHAR))
637 {
638 Name[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
639 }
640
641 *NameSize = NameLength + sizeof(WCHAR);
642
643 HvReleaseCell(Hive, CellIndex);
644
645 if (SubKey != NULL)
646 *SubKey = HCI_TO_HKEY(CellIndex);
647
648 TRACE("RegEnumKey done -> %u, '%.*S'\n", *NameSize, *NameSize, Name);
649 return ERROR_SUCCESS;
650}
651#endif
652
653LONG
658{
659 UNICODE_STRING RemainingPath, SubKeyName;
660 UNICODE_STRING CurrentControlSet = RTL_CONSTANT_STRING(L"CurrentControlSet");
662 PCM_KEY_NODE KeyNode;
663 HCELL_INDEX CellIndex;
664
665 TRACE("RegOpenKey(%p, '%S', %p)\n", ParentKey, KeyName, Key);
666
667 /* Initialize the remaining path name */
668 RtlInitUnicodeString(&RemainingPath, KeyName);
669
670 /* Check if we have a parent key */
671 if (ParentKey == NULL)
672 {
673 UNICODE_STRING SubKeyName1, SubKeyName2, SubKeyName3;
675 UNICODE_STRING MachinePath = RTL_CONSTANT_STRING(L"MACHINE");
676 UNICODE_STRING SystemPath = RTL_CONSTANT_STRING(L"SYSTEM");
677
678 TRACE("RegOpenKey: absolute path\n");
679
680 if ((RemainingPath.Length < sizeof(WCHAR)) ||
681 RemainingPath.Buffer[0] != '\\')
682 {
683 /* The key path is not absolute */
684 ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
686 }
687
688 /* Skip initial path separator */
689 RemainingPath.Buffer++;
690 RemainingPath.Length -= sizeof(WCHAR);
691
692 /* Get the first 3 path elements */
693 GetNextPathElement(&SubKeyName1, &RemainingPath);
694 GetNextPathElement(&SubKeyName2, &RemainingPath);
695 GetNextPathElement(&SubKeyName3, &RemainingPath);
696 TRACE("RegOpenKey: %wZ / %wZ / %wZ\n", &SubKeyName1, &SubKeyName2, &SubKeyName3);
697
698 /* Check if we have the correct path */
699 if (!RtlEqualUnicodeString(&SubKeyName1, &RegistryPath, TRUE) ||
700 !RtlEqualUnicodeString(&SubKeyName2, &MachinePath, TRUE) ||
701 !RtlEqualUnicodeString(&SubKeyName3, &SystemPath, TRUE))
702 {
703 /* The key path is not inside HKLM\Machine\System */
704 ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
706 }
707
708 /* Use the root key */
709 CellIndex = SystemRootCell;
710 }
711 else
712 {
713 /* Use the parent key */
714 CellIndex = HKEY_TO_HCI(ParentKey);
715 }
716
717 /* Check if this is the root key */
718 if (CellIndex == SystemRootCell)
719 {
720 UNICODE_STRING TempPath = RemainingPath;
721
722 /* Get the first path element */
723 GetNextPathElement(&SubKeyName, &TempPath);
724
725 /* Check if this is CurrentControlSet */
726 if (RtlEqualUnicodeString(&SubKeyName, &CurrentControlSet, TRUE))
727 {
728 /* Use the CurrentControlSetKey and update the remaining path */
730 RemainingPath = TempPath;
731 }
732 }
733
734 /* Get the key node */
735 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
736 ASSERT(KeyNode);
738
739 TRACE("RegOpenKey: RemainingPath '%wZ'\n", &RemainingPath);
740
741 /* Loop while there are path elements */
742 while (GetNextPathElement(&SubKeyName, &RemainingPath))
743 {
744 HCELL_INDEX NextCellIndex;
745
746 TRACE("RegOpenKey: next element '%wZ'\n", &SubKeyName);
747
748 /* Get the next sub key */
749 NextCellIndex = CmpFindSubKeyByName(Hive, KeyNode, &SubKeyName);
750 HvReleaseCell(Hive, CellIndex);
751 CellIndex = NextCellIndex;
752 if (CellIndex == HCELL_NIL)
753 {
754 WARN("Did not find sub key '%wZ' (full: %S)\n", &SubKeyName, KeyName);
756 }
757
758 /* Get the found key */
759 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, CellIndex);
760 ASSERT(KeyNode);
762 }
763
764 HvReleaseCell(Hive, CellIndex);
765 *Key = HCI_TO_HKEY(CellIndex);
766
767 return ERROR_SUCCESS;
768}
769
770static
771VOID
773 _In_ PHHIVE Hive,
774 _In_ PCM_KEY_VALUE ValueCell,
778{
780 PVOID DataCell;
781
782 /* Does the caller want the type? */
783 if (Type != NULL)
784 *Type = ValueCell->Type;
785
786 /* Does the caller provide DataSize? */
787 if (DataSize != NULL)
788 {
789 // NOTE: CmpValueToData doesn't support big data (the function will
790 // bugcheck if so), FreeLdr is not supposed to read such data.
791 // If big data is needed, use instead CmpGetValueData.
792 // CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...);
793 DataCell = CmpValueToData(Hive, ValueCell, &DataLength);
794
795 /* Does the caller want the data? */
796 if ((Data != NULL) && (*DataSize != 0))
797 {
799 DataCell,
801 }
802
803 /* Return the actual data length */
805 }
806}
807
808LONG
810 _In_ HKEY Key,
815{
817 PCM_KEY_NODE KeyNode;
818 PCM_KEY_VALUE ValueCell;
819 HCELL_INDEX CellIndex;
820 UNICODE_STRING ValueNameString;
821
822 TRACE("RegQueryValue(%p, '%S', %p, %p, %p)\n",
824
825 /* Get the key node */
826 KeyNode = GET_CM_KEY_NODE(Hive, Key);
827 ASSERT(KeyNode);
829
830 /* Initialize value name string */
831 RtlInitUnicodeString(&ValueNameString, ValueName);
832 CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString);
833 if (CellIndex == HCELL_NIL)
834 {
835 TRACE("RegQueryValue value not found in key (%.*s)\n",
836 KeyNode->NameLength, KeyNode->Name);
839 }
841
842 /* Get the value cell */
843 ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
844 ASSERT(ValueCell != NULL);
845
846 RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
847
848 HvReleaseCell(Hive, CellIndex);
849
850 return ERROR_SUCCESS;
851}
852
853/*
854 * NOTE: This function is currently unused in FreeLdr; however it is kept here
855 * as an implementation reference of RegEnumValue using CMLIB that may be used
856 * elsewhere in ReactOS.
857 */
858#if 0
859LONG
861 _In_ HKEY Key,
864 _Inout_ PULONG NameSize,
868{
870 PCM_KEY_NODE KeyNode;
871 PCELL_DATA ValueListCell;
872 PCM_KEY_VALUE ValueCell;
873 USHORT NameLength;
874
875 TRACE("RegEnumValue(%p, %lu, %S, %p, %p, %p, %p (%lu))\n",
876 Key, Index, ValueName, NameSize, Type, Data, DataSize, *DataSize);
877
878 /* Get the key node */
879 KeyNode = GET_CM_KEY_NODE(Hive, Key);
880 ASSERT(KeyNode);
882
883 /* Check if the index is valid */
884 if ((KeyNode->ValueList.Count == 0) ||
885 (KeyNode->ValueList.List == HCELL_NIL) ||
886 (Index >= KeyNode->ValueList.Count))
887 {
888 ERR("RegEnumValue: index invalid\n");
890 return ERROR_NO_MORE_ITEMS;
891 }
892
893 ValueListCell = (PCELL_DATA)HvGetCell(Hive, KeyNode->ValueList.List);
894 ASSERT(ValueListCell != NULL);
895
896 /* Get the value cell */
897 ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, ValueListCell->KeyList[Index]);
898 ASSERT(ValueCell != NULL);
900
901 if (ValueCell->Flags & VALUE_COMP_NAME)
902 {
903 NameLength = CmpCompressedNameSize(ValueCell->Name, ValueCell->NameLength);
904
905 /* Compressed name */
907 *NameSize,
908 ValueCell->Name,
909 ValueCell->NameLength);
910 }
911 else
912 {
913 NameLength = ValueCell->NameLength;
914
915 /* Normal name */
916 RtlCopyMemory(ValueName, ValueCell->Name,
917 min(*NameSize, ValueCell->NameLength));
918 }
919
920 if (*NameSize >= NameLength + sizeof(WCHAR))
921 {
922 ValueName[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
923 }
924
925 *NameSize = NameLength + sizeof(WCHAR);
926
927 RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
928
929 HvReleaseCell(Hive, ValueListCell->KeyList[Index]);
930 HvReleaseCell(Hive, KeyNode->ValueList.List);
932
933 TRACE("RegEnumValue done -> %u, '%.*S'\n", *NameSize, *NameSize, ValueName);
934 return ERROR_SUCCESS;
935}
936#endif
937
938/* EOF */
unsigned char BOOLEAN
Type
Definition: Type.h:7
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:462
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
ARC_STATUS ArcOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fs.c:219
ARC_STATUS ArcClose(_In_ ULONG FileId)
Definition: fs.c:409
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: heap.c:539
PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: heap.c:533
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
static BOOLEAN RegRecoverHeaderHive(_Inout_ PVOID ChunkBase, _In_ PCSTR DirectoryPath, _In_ PCSTR LogName)
Recovers the header base block of a flat registry hive.
Definition: registry.c:277
#define GET_CM_KEY_NODE(hHive, hKey)
Definition: registry.c:43
static BOOLEAN GetNextPathElement(_Out_ PUNICODE_STRING NextElement, _Inout_ PUNICODE_STRING RemainingPath)
Definition: registry.c:541
BOOLEAN RegInitCurrentControlSet(_In_ BOOLEAN LastKnownGood)
Definition: registry.c:503
static VOID RepGetValueData(_In_ PHHIVE Hive, _In_ PCM_KEY_VALUE ValueCell, _Out_opt_ PULONG Type, _Out_opt_ PUCHAR Data, _Inout_opt_ PULONG DataSize)
Definition: registry.c:772
#define GET_HBASE_BLOCK(ChunkBase)
Definition: registry.c:45
VOID NTAPI CmpFree(IN PVOID Ptr, IN ULONG Quota)
Definition: registry.c:60
static BOOLEAN RegLoadHiveLog(_In_ PCSTR DirectoryPath, _In_ ULONG LogFileOffset, _In_ PCSTR LogName, _Out_ PVOID *LogData)
Loads and reads a hive log at specified file offset.
Definition: registry.c:170
#define GET_HHIVE(CmHive)
Definition: registry.c:41
static PCMHIVE CmSystemHive
Definition: registry.c:30
PHHIVE SystemHive
Definition: registry.c:33
static HCELL_INDEX SystemRootCell
Definition: registry.c:31
BOOLEAN RegImportBinaryHive(_In_ PVOID ChunkBase, _In_ ULONG ChunkSize, _In_ PCSTR SearchPath, _In_ BOOLEAN LoadAlternate)
Imports the SYSTEM binary hive from the registry base chunk that's been provided by the loader block.
Definition: registry.c:436
HKEY CurrentControlSetKey
Definition: registry.c:34
#define HCI_TO_HKEY(CellIndex)
Definition: registry.c:36
PVOID NTAPI CmpAllocate(IN SIZE_T Size, IN BOOLEAN Paged, IN ULONG Tag)
Definition: registry.c:49
static BOOLEAN RegInitializeHive(_In_ PCMHIVE CmHive, _In_ PVOID ChunkBase, _In_ BOOLEAN LoadAlternate)
Initializes a flat hive descriptor for the hive and validates the registry hive. Volatile data is pur...
Definition: registry.c:96
#define GET_HHIVE_FROM_HKEY(hKey)
Definition: registry.c:42
static BOOLEAN RegRecoverDataHive(_Inout_ PVOID ChunkBase, _In_ PCSTR DirectoryPath, _In_ PCSTR LogName)
Recovers the corrupt data of a primary flat registry hive.
Definition: registry.c:350
#define HKEY_TO_HCI(hKey)
Definition: registry.h:28
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
HCELL_INDEX NTAPI CmpFindControlSet(_In_ PHHIVE SystemHive, _In_ HCELL_INDEX RootCell, _In_ PCUNICODE_STRING SelectKeyName, _Out_ PBOOLEAN AutoSelect)
Finds the corresponding "HKLM\SYSTEM\ControlSetXXX" system control set registry key,...
Definition: cmboot.c:84
CM_CHECK_REGISTRY_STATUS NTAPI CmCheckRegistry(_In_ PCMHIVE RegistryHive, _In_ ULONG Flags)
Checks the registry that is consistent and its contents valid and not corrupted. More specifically th...
Definition: cmcheck.c:1634
struct _CELL_DATA * PCELL_DATA
struct _CM_KEY_NODE * PCM_KEY_NODE
#define KEY_COMP_NAME
Definition: cmdata.h:35
struct _CM_KEY_VALUE * PCM_KEY_VALUE
#define CM_KEY_VALUE_SIGNATURE
Definition: cmdata.h:24
#define VALUE_COMP_NAME
Definition: cmdata.h:44
#define CM_KEY_NODE_SIGNATURE
Definition: cmdata.h:21
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
#define HvReleaseCell(Hive, Cell)
Definition: cmlib.h:460
BOOLEAN CMAPI HvpVerifyHiveHeader(_In_ PHBASE_BLOCK BaseBlock, _In_ ULONG FileType)
Validates the base block header of a registry file (hive or log).
Definition: hiveinit.c:49
ULONG CMAPI HvpHiveHeaderChecksum(PHBASE_BLOCK HiveHeader)
Definition: hivesum.c:17
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
NTSTATUS CMAPI HvInitialize(PHHIVE RegistryHive, ULONG OperationType, ULONG HiveFlags, ULONG FileType, PVOID HiveData OPTIONAL, PALLOCATE_ROUTINE Allocate, PFREE_ROUTINE Free, PFILE_SET_SIZE_ROUTINE FileSetSize, PFILE_WRITE_ROUTINE FileWrite, PFILE_READ_ROUTINE FileRead, PFILE_FLUSH_ROUTINE FileFlush, ULONG Cluster OPTIONAL, PCUNICODE_STRING FileName OPTIONAL)
#define CM_CHECK_REGISTRY_VALIDATE_HIVE
Definition: cmlib.h:231
HCELL_INDEX NTAPI CmpFindValueByName(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name)
Definition: cmvalue.c:99
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode)
Definition: cmlib.h:281
ULONG CM_CHECK_REGISTRY_STATUS
Definition: cmlib.h:223
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE_VOLATILES
Definition: cmlib.h:230
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:457
FORCEINLINE PVOID VaToPa(PVOID Va)
Definition: conversion.h:15
FORCEINLINE PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
#define ERROR_SUCCESS
Definition: deptool.c:10
LPWSTR Name
Definition: desk.c:124
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define MAX_PATH
Definition: compat.h:34
@ Success
Definition: eventcreate.c:712
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:25
#define HBLOCK_SIZE
Definition: hivedata.h:42
#define HV_LOG_HEADER_SIZE
Definition: hivedata.h:46
#define HFILE_TYPE_ALTERNATE
Definition: hivedata.h:36
#define HFILE_TYPE_LOG
Definition: hivedata.h:34
#define HINIT_FLAT
Definition: hivedata.h:17
#define HFILE_TYPE_PRIMARY
Definition: hivedata.h:33
#define HCELL_NIL
Definition: hivedata.h:110
#define HBOOT_BOOT_RECOVERED_BY_HIVE_LOG
Definition: hivedata.h:95
#define HV_LOG_DIRTY_BLOCK
Definition: hivedata.h:56
ULONG HCELL_INDEX
Definition: hivedata.h:105
#define HBOOT_NO_BOOT_RECOVER
Definition: hivedata.h:94
struct _HBASE_BLOCK * PHBASE_BLOCK
#define HV_LOG_DIRTY_SIGNATURE
Definition: hivedata.h:57
#define HSECTOR_SIZE
Definition: hivedata.h:43
#define ASSERT(a)
Definition: mode.c:44
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define min(a, b)
Definition: monoChain.cc:55
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _In_z_
Definition: no_sal2.h:164
#define _Inout_opt_
Definition: no_sal2.h:216
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
NTSTRSAFEAPI RtlStringCbCatA(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:625
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
@ ESUCCESS
Definition: arc.h:32
@ LoaderRegistryData
Definition: arc.h:193
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekAbsolute
Definition: arc.h:59
@ OpenReadOnly
Definition: arc.h:65
#define TRACE(s)
Definition: solgame.cpp:4
HCELL_INDEX KeyList[ANYSIZE_ARRAY]
Definition: cmdata.h:205
HCELL_INDEX List
Definition: cmdata.h:75
ULONG Count
Definition: cmdata.h:74
Definition: cmlib.h:316
USHORT Signature
Definition: cmdata.h:92
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
USHORT NameLength
Definition: cmdata.h:114
CHILD_LIST ValueList
Definition: cmdata.h:103
USHORT Flags
Definition: cmdata.h:93
USHORT Signature
Definition: cmdata.h:124
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:131
USHORT NameLength
Definition: cmdata.h:125
USHORT Flags
Definition: cmdata.h:129
ULONG Length
Definition: hivedata.h:171
HCELL_INDEX RootCell
Definition: hivedata.h:168
ULONG Sequence1
Definition: hivedata.h:147
ULONG Type
Definition: hivedata.h:161
ULONG CheckSum
Definition: hivedata.h:183
ULONG Sequence2
Definition: hivedata.h:148
ULONG Cluster
Definition: hivedata.h:174
PHBASE_BLOCK BaseBlock
Definition: hivedata.h:328
static COORD Position
Definition: mouse.c:34
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_Must_inspect_result_ _In_opt_ WDFKEY ParentKey
Definition: wdfregistry.h:69
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
#define SearchPath
Definition: winbase.h:3931
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define RegOpenKey
Definition: winreg.h:519
#define RegEnumValue
Definition: winreg.h:511
#define RegQueryValue
Definition: winreg.h:523
#define RegEnumKey
Definition: winreg.h:509
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2294
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175